diff --git a/.github/workflows/master-build.yaml b/.github/workflows/master-build.yaml new file mode 100644 index 0000000..e56332f --- /dev/null +++ b/.github/workflows/master-build.yaml @@ -0,0 +1,97 @@ +name: Build metrics-provider + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + vm-job: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + + - name: set root own + run: sudo chown 0:0 / + + - name: Get Skaffold + env: + KUBECONFIG: /tmp/config + run: | + curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 && chmod uo+x skaffold && sudo mv skaffold /usr/local/bin + skaffold version + + - name: Install snap core + run: sudo snap install core + + - name: install microk8s + run: sudo snap install microk8s --classic --edge + + - name: Set kubectl alias + run: sudo snap alias microk8s.kubectl kubectl + + - name: Enable RBAC addons + run: sudo microk8s.enable rbac + + - name: Enable DNS addons + run: | + sudo microk8s.enable dns + sleep 60 # wait for apiserver to be up and running + sudo microk8s.kubectl wait --for=condition=available --timeout=600s deployment/coredns -n kube-system + + - name: Enable storage addons + run: | + sudo microk8s.enable storage + sudo microk8s.kubectl wait --for=condition=available --timeout=600s deployment/hostpath-provisioner -n kube-system + + - name: Enable Helm addon + run: | + sudo microk8s.enable helm + + cat < /tmp/config + export KUBECONFIG=/tmp/config + + mkdir -p ~/.docker/ + echo $REGCRED > ~/.docker/config.json + sudo microk8s.kubectl create ns artemis + sudo microk8s.kubectl -n artemis create secret generic regcred --from-file ~/.docker/config.json + + skaffold run -p metrics-provider + + sudo microk8s.kubectl -n artemis wait --for=condition=available --timeout=600s deployment/artemis-activemq -n artemis + sudo microk8s.kubectl -n artemis get pods -o wide diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..257eb25 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +**/target/ +**/.idea/ +**/*.iml +**/.vscode/ +**/.classpath +**/.project +**/.settings/ +**/artemis-ext-scaler \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c159435 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 balchua + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..25e87cb --- /dev/null +++ b/README.md @@ -0,0 +1,207 @@ +# Keda External Scaler with ActiveMQ Artemis + +This is a demonstration on how to use KEDA's external scaler to monitor [ActiveMQ Artemis](https://activemq.apache.org/components/artemis/) Queue. + +The Keda external scaler calls metrics-provider GRPC server which will collect the metrics from ActiveMQ Artemis. + +**Note: use your own docker repository while building the project.** + +## Pre-requisites: + +* Kubernetes cluster +* Keda installed in the cluster. +* skaffold - used to build the images +* maven - use to build the java consumer and producer project. + +## Code organization + +* consumer - a simple Springboot application which consumes messages from ActiveMQ Artemis. The queue name used is `test`. The `consumerWindowSize` is also set to `0` so that it will not buffer the messages to one consumer. +* producer - a simple Springboot application which pumps messages to the queue `test` +* metrics-provider - a Go application which serves as the GRPC server to serve the Keda External Scaler. It queries ActiveMQ Artemis `MessageCount` using the built -in jolokia endpoint exposed by Artemis. +* k8s-manifest - everything Kubernetes + +### Building the metrics provider for external scaler + +You can get the `proto` file from the Keda [github](https://github.com/kedacore/keda/blob/master/pkg/scalers/externalscaler/externalscaler.proto). + +This project already contains the [`externalscaler.proto`](metrics-provider/externalscaler/proto/externalscaler.proto) + +### Use protoc to autogenerate the Proto codes. + +`protoc -I externalscaler/ externalscaler/proto/externalscaler.proto --go_out=plugins=grpc:externalscaler` + +**Note: We use kaniko in-cluster builder** + +#### Setup kaniko registry access secret + +`kubectl -n artemis create secret generic regcred --from-file $HOME/.docker/config.json` + +```shell +$ skaffold run -p metrics-provider +``` + +### External Scaler as ActiveMQ Artemis sidecar + +The docker image used taken from [vromero/activemq-artemis-docker](https://github.com/vromero/activemq-artemis-docker) uses the `hostname` as its broker name, in order to avoid hardcoding the broker name, the metrics provider is deployed as a _sidecar_ to ActiveMQ Artemis. + +Added to the file [`k8s-manifest/artemis/deployment.yaml`](k8s-manifest/artemis/deployment.yaml) + +```yaml + containers: + - name: artemis-activemq-metrics-provider + image: docker.io/balchu/artemis-ext-scaler:1.0.0 + args: ["--port","5050","--broker","$(POD_NAME)", "--user", "$(ARTEMIS_USERNAME)","--password","${ARTEMIS_PASSWOORD)"] + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 10Mi +``` + +### Build and deploy the consumer. + +Using skaffold and jib, simply execute the command below. + +`skaffold run -p consumer` + +Please make sure that you use your docker repository. + +### Deploy the External Scaler manifest + +Now its time to setup the KEDA's external scaler. + +`kubectl apply -f k8s-manifest/externalscaler_scaledobject.yaml` + +The file looks like this. + +```yaml +apiVersion: keda.k8s.io/v1alpha1 +kind: ScaledObject +metadata: + name: artemis-scaledobject + namespace: artemis + labels: + deploymentName: artemis-consumer +spec: + pollingInterval: 10 # Optional. Default: 30 seconds + cooldownPeriod: 100 # Optional. Default: 300 seconds + minReplicaCount: 0 # Optional. Default: 0 + maxReplicaCount: 30 # Optional. Default: 100 + scaleTargetRef: + deploymentName: artemis-consumer + triggers: + - type: external + metadata: + scalerAddress: artemis-activemq.artemis:5050 + queueLength: "10" + brokerAddress: "test" + queueName: "test" +``` + +Where: +* `scalerAddress`: is the location of the GRPC metrics provider host and port. +* `queueLength`: the target queue length. +* `brokerAddress`: An address represents a messaging endpoint. Within the configuration, a typical address is given a unique name, 0 or more queues, and a routing type. +* `queueName`: the name of queue to monitor. + +Before pumping in messages, check the HPA. + +### Check the HPA + +```shell + +kubectl -n artemis get hpa +NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE +keda-hpa-artemis-consumer Deployment/artemis-consumer /20 (avg) 1 30 0 58m + +``` + +At this point,HPA doesn't have the `TargetAverageValue` to scale up or down the pods. This can be observed by the `/20(avg)` + + +### Start the producer + +The producer is a simple Springboot application. + +If you are going to run the Springboot application using your IDE, make sure that you point to the host and port of the ActiveMQ Artemis. + +Check the file [application.yml](producer/src/main/resources/application.yml) + +As an example: + +```yaml +spring: + artemis: + mode: native + host: ${ARTEMIS_SERVER_HOST:10.152.183.227} + port: ${ARTEMIS_SERVER_PORT:61616} + user: ${ARTEMIS_USERNAME:artemis} + password: ${ARTEMIS_PASSWORD:artemis} +``` + +In the Class [App.java](producer/src/main/java/org/bal/starter/App.java) + +You can modify how much messages you want to send to the broker. In the example below, the program is pushing 10000 messages to the broker, with a delay of 200 milliseonds. + +```java +public void run(String... args) throws Exception { + for (int i = 0; i < 10000; i++){ + producer.send("Message is: " + System.currentTimeMillis()); + sleep(200); + } +} +``` + +### Checking the scaling up of the pods. + +```shell + +$ kubectl -n artemis get pods +NAME READY STATUS RESTARTS AGE +artemis-activemq-66c66ffdcc-9f7hq 2/2 Running 0 15m +artemis-consumer-589c9b87f7-mldrx 0/1 ContainerCreating 0 4s +artemis-consumer-589c9b87f7-mltqx 1/1 Running 0 14s +``` + +### Scale to zero + +Once you stop the producer program, KEDA will determine that messages are no longer coming and will scale down the pods to zero. + +```shell +$kubectl -n artemis get pods -w +NAME READY STATUS RESTARTS AGE +artemis-activemq-66c66ffdcc-9f7hq 2/2 Running 0 16m +artemis-consumer-589c9b87f7-8xwq6 1/1 Running 0 43s +artemis-consumer-589c9b87f7-k2bf5 1/1 Running 0 12s +artemis-consumer-589c9b87f7-mldrx 1/1 Running 0 58s +artemis-consumer-589c9b87f7-mltqx 1/1 Running 0 68s +artemis-consumer-589c9b87f7-mltqx 1/1 Terminating 0 81s +artemis-consumer-589c9b87f7-8xwq6 1/1 Terminating 0 56s +artemis-consumer-589c9b87f7-mldrx 1/1 Terminating 0 71s +artemis-consumer-589c9b87f7-k2bf5 1/1 Terminating 0 25s +artemis-consumer-589c9b87f7-8xwq6 0/1 Terminating 0 57s +artemis-consumer-589c9b87f7-mldrx 0/1 Terminating 0 72s +artemis-consumer-589c9b87f7-k2bf5 0/1 Terminating 0 27s +artemis-consumer-589c9b87f7-mldrx 0/1 Terminating 0 73s +artemis-consumer-589c9b87f7-mldrx 0/1 Terminating 0 73s +artemis-consumer-589c9b87f7-mltqx 0/1 Terminating 0 83s + +``` + +### Clean up + +Delete the consumer + +`skaffold delete -p consumer ` + +Delete ActiveMQ Artemis and the metrics provider + +`skaffold delete -p metrics-provider` + +Delete the External Scaler object + +`kubectl delete -f k8s-manifest/externalscaler_scaledobject.yaml` + +Verify that the HPA is successfully deleted + +`kubectl -n artemis get hpa` \ No newline at end of file diff --git a/consumer/pom.xml b/consumer/pom.xml new file mode 100644 index 0000000..e7e67bc --- /dev/null +++ b/consumer/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + artemis-consumer + jar + consumer + org.bal.app + 0.0.4 + SpringBootArtemisConsumer + + + org.springframework.boot + spring-boot-starter-parent + 2.1.6.RELEASE + + + UTF-8 + UTF-8 + 11 + 1.4.0 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework + spring-jms + + + + org.springframework.boot + spring-boot-starter-artemis + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + + org.bal.starter.App + ZIP + + spring-boot-maven-plugin + + + + repackage + + + + + + + + maven-resources-plugin + ${maven-resources-plugin.version} + + + filter-dockerfile + process-resources + + copy-resources + + + ${project.build.directory} + + + src/main/docker + true + + + + + + + + + com.google.cloud.tools + jib-maven-plugin + ${jib-version} + + true + + adoptopenjdk/openjdk11:jdk-11.0.3_7-debian-slim + + + true + + -Djava.security.egd=file:/dev/./urandom + + + + 192.168.1.12:32000/${project.artifactId}:${project.version} + + + + + + + + \ No newline at end of file diff --git a/consumer/src/main/java/org/bal/config/ConsumerConfiguration.java b/consumer/src/main/java/org/bal/config/ConsumerConfiguration.java new file mode 100644 index 0000000..ba77d85 --- /dev/null +++ b/consumer/src/main/java/org/bal/config/ConsumerConfiguration.java @@ -0,0 +1,50 @@ +package org.bal.config; + +import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; +import org.bal.consumer.Consumer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jms.annotation.EnableJms; +import org.springframework.jms.config.DefaultJmsListenerContainerFactory; + +@Configuration +@EnableJms +public class ConsumerConfiguration { + + + @Value("${artemis.host}") + private String brokerHost; + + @Value("${artemis.port}") + private int brokerPort; + + @Value("${artemis.user}") + private String user; + + @Value("${artemis.password}") + private String password; + + @Bean + public ActiveMQConnectionFactory receiverActiveMQConnectionFactory() { + ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://" + brokerHost+":" + brokerPort); + factory.setConsumerWindowSize(0); + factory.setUser(user); + factory.setPassword(password); + return factory; + } + + @Bean + public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() { + DefaultJmsListenerContainerFactory factory = + new DefaultJmsListenerContainerFactory(); + factory.setConnectionFactory(receiverActiveMQConnectionFactory()); + //factory.setConcurrency("3-10"); + + return factory; + } + @Bean + public Consumer receiver() { + return new Consumer(); + } +} \ No newline at end of file diff --git a/consumer/src/main/java/org/bal/consumer/Consumer.java b/consumer/src/main/java/org/bal/consumer/Consumer.java new file mode 100644 index 0000000..4544edb --- /dev/null +++ b/consumer/src/main/java/org/bal/consumer/Consumer.java @@ -0,0 +1,24 @@ +package org.bal.consumer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jms.annotation.JmsListener; + +import static java.lang.Thread.*; + +public class Consumer { + + private static final Logger LOGGER = + LoggerFactory.getLogger(Consumer.class); + + @JmsListener(destination = "test", concurrency = "1") + public void receive(String message) throws IllegalAccessException { + try { + sleep(1000); + LOGGER.info("received message='{}' ......", message); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } +} \ No newline at end of file diff --git a/consumer/src/main/java/org/bal/starter/App.java b/consumer/src/main/java/org/bal/starter/App.java new file mode 100644 index 0000000..532d103 --- /dev/null +++ b/consumer/src/main/java/org/bal/starter/App.java @@ -0,0 +1,13 @@ +package org.bal.starter; + +import org.bal.config.ConsumerConfiguration; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication(scanBasePackageClasses = {ConsumerConfiguration.class}, scanBasePackages = "org.bal") +public class App { + + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } +} \ No newline at end of file diff --git a/consumer/src/main/resources/application.yml b/consumer/src/main/resources/application.yml new file mode 100644 index 0000000..99d223e --- /dev/null +++ b/consumer/src/main/resources/application.yml @@ -0,0 +1,10 @@ +artemis: + host: ${ARTEMIS_SERVER_HOST:10.152.183.203} + port: ${ARTEMIS_SERVER_PORT:61616} + user: ${ARTEMIS_USERNAME:artemis} + password: ${ARTEMIS_PASSWORD:artemis} + +logging: + level: + root: WARN + org.bal: INFO \ No newline at end of file diff --git a/k8s-manifest/artemis/deployment.yaml b/k8s-manifest/artemis/deployment.yaml new file mode 100644 index 0000000..100e107 --- /dev/null +++ b/k8s-manifest/artemis/deployment.yaml @@ -0,0 +1,179 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: artemis-activemq + namespace: artemis + labels: + app: activemq-artemis +type: Opaque +data: + artemis-password: "YXJ0ZW1pcw==" + + +--- +apiVersion: v1 +kind: Service +metadata: + name: artemis-activemq + namespace: artemis + labels: + app: activemq-artemis +spec: + ports: + - name: http + port: 8161 + targetPort: http + - name: core + port: 61616 + targetPort: core + - name: amqp + port: 5672 + targetPort: amqp + - name: jmx + port: 9494 + targetPort: jmxexporter + - name: grpc + port: 5050 + targetPort: grpc + + selector: + app: activemq-artemis + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: artemis-activemq-cm + namespace: artemis +data: + broker-00.xml: | + + + + + + +
+ + + +
+
+
+
+ + configure-cluster.sh: | + + set -e + echo Copying common configuration + cp /data/etc-override/*.xml /var/lib/artemis/etc-override/broker-10.xml + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: artemis-activemq + namespace: artemis + labels: + app: activemq-artemis +spec: + replicas: 1 + revisionHistoryLimit: 1 + selector: + matchLabels: + app: activemq-artemis + template: + metadata: + name: artemis-activemq-artemis + labels: + app: activemq-artemis + spec: + initContainers: + - name: configure-cluster + image: docker.io/vromero/activemq-artemis:2.6.2 + command: ["/bin/sh", "/data/etc-override/configure-cluster.sh"] + volumeMounts: + - name: config-override + mountPath: /var/lib/artemis/etc-override + - name: configmap-override + mountPath: /data/etc-override/ + containers: + - name: artemis-activemq-metrics-provider + image: balchu/artemis-ext-scaler + args: ["--port","5050","--broker","$(POD_NAME)","--user", "$(ARTEMIS_USERNAME)","--password","${ARTEMIS_PASSWOORD)"] + imagePullPolicy: Always + resources: + requests: + cpu: 100m + memory: 10Mi + env: + - name: ARTEMIS_PASSWORD + valueFrom: + secretKeyRef: + name: artemis-activemq + key: artemis-password + - name: ARTEMIS_USERNAME + value: "artemis" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + ports: + - name: grpc + containerPort: 5050 + + - name: artemis-activemq-artemis + image: docker.io/vromero/activemq-artemis:2.6.2 + imagePullPolicy: + resources: + requests: + cpu: 100m + memory: 256Mi + env: + - name: ARTEMIS_PASSWORD + valueFrom: + secretKeyRef: + name: artemis-activemq + key: artemis-password + - name: ARTEMIS_USERNAME + value: "artemis" + - name: ARTEMIS_PERF_JOURNAL + value: "AUTO" + - name: ENABLE_JMX_EXPORTER + value: "true" + ports: + - name: http + containerPort: 8161 + - name: core + containerPort: 61616 + - name: amqp + containerPort: 5672 + - name: jmxexporter + containerPort: 9404 + livenessProbe: + tcpSocket: + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + readinessProbe: + tcpSocket: + port: core + initialDelaySeconds: 10 + periodSeconds: 10 + volumeMounts: + - name: data + mountPath: /var/lib/artemis/data + - name: config-override + mountPath: /var/lib/artemis/etc-override + volumes: + - name: data + emptyDir: {} + - name: config-override + emptyDir: {} + - name: configmap-override + configMap: + name: artemis-activemq-cm + + + diff --git a/k8s-manifest/consumer-deployment.yaml b/k8s-manifest/consumer-deployment.yaml new file mode 100644 index 0000000..dfcf8e8 --- /dev/null +++ b/k8s-manifest/consumer-deployment.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: artemis-consumer + namespace: artemis +spec: + selector: + matchLabels: + app: artemis-consumer + replicas: 1 + template: + metadata: + labels: + app: artemis-consumer + spec: + containers: + - name: artemis-consumer + image: 192.168.1.12:32000/artemis-consumer + imagePullPolicy: Always + env: + - name: ARTEMIS_PASSWORD + valueFrom: + secretKeyRef: + name: artemis-activemq + key: artemis-password + - name: ARTEMIS_USERNAME + value: "artemis" + - name: ARTEMIS_HOST + value: "artemis-activemq" + - name: ARTEMIS_PORT + value: "61616" \ No newline at end of file diff --git a/k8s-manifest/externalscaler_scaledobject.yaml b/k8s-manifest/externalscaler_scaledobject.yaml new file mode 100644 index 0000000..c1c43bd --- /dev/null +++ b/k8s-manifest/externalscaler_scaledobject.yaml @@ -0,0 +1,22 @@ +apiVersion: keda.k8s.io/v1alpha1 +kind: ScaledObject +metadata: + name: artemis-scaledobject + namespace: artemis + labels: + deploymentName: artemis-consumer +spec: + pollingInterval: 10 # Optional. Default: 30 seconds + cooldownPeriod: 100 # Optional. Default: 300 seconds + minReplicaCount: 0 # Optional. Default: 0 + maxReplicaCount: 30 # Optional. Default: 100 + scaleTargetRef: + deploymentName: artemis-consumer + triggers: + - type: external + metadata: + scalerAddress: artemis-activemq.artemis:5050 + queueLength: "10" + brokerAddress: "test" + queueName: "test" + diff --git a/k8s-manifest/sample-deployment.yaml b/k8s-manifest/sample-deployment.yaml new file mode 100644 index 0000000..c83985d --- /dev/null +++ b/k8s-manifest/sample-deployment.yaml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 +kind: Deployment +metadata: + name: nginx-deployment + namespace: artemis +spec: + selector: + matchLabels: + app: nginx + replicas: 1 # tells deployment to run 2 pods matching the template + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 \ No newline at end of file diff --git a/metrics-provider/Dockerfile b/metrics-provider/Dockerfile new file mode 100644 index 0000000..ebcbd23 --- /dev/null +++ b/metrics-provider/Dockerfile @@ -0,0 +1,24 @@ +# Use base golang image from Docker Hub +FROM golang:1.13.3 as build + +WORKDIR /src/github.com/balchua/artemis-ext-scaler + +# Copy go.mod and go.sum +ADD ./go.mod /src/github.com/balchua/artemis-ext-scaler/ +ADD ./go.sum /src/github.com/balchua/artemis-ext-scaler/ +# Install dependencies in go.mod and go.sum +RUN go mod download + +# Copy application source code +COPY ./server.go /src/github.com/balchua/artemis-ext-scaler/ +COPY ./externalscaler/ /src/github.com/balchua/artemis-ext-scaler/externalscaler + +# Compile the application to /app. +RUN go build -o /app -v . + +# Now create separate deployment image +FROM gcr.io/distroless/base +COPY --from=build /app /app +# Cause full tracebacks; also serves to identify this image as a Go image for `skaffold debug` +ENV GOTRACEBACK=all +ENTRYPOINT ["/app"] diff --git a/metrics-provider/externalscaler/proto/externalscaler.pb.go b/metrics-provider/externalscaler/proto/externalscaler.pb.go new file mode 100644 index 0000000..ab2218d --- /dev/null +++ b/metrics-provider/externalscaler/proto/externalscaler.pb.go @@ -0,0 +1,651 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: proto/externalscaler.proto + +package externalscaler + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + empty "github.com/golang/protobuf/ptypes/empty" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type ScaledObjectRef struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ScaledObjectRef) Reset() { *m = ScaledObjectRef{} } +func (m *ScaledObjectRef) String() string { return proto.CompactTextString(m) } +func (*ScaledObjectRef) ProtoMessage() {} +func (*ScaledObjectRef) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{0} +} + +func (m *ScaledObjectRef) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ScaledObjectRef.Unmarshal(m, b) +} +func (m *ScaledObjectRef) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ScaledObjectRef.Marshal(b, m, deterministic) +} +func (m *ScaledObjectRef) XXX_Merge(src proto.Message) { + xxx_messageInfo_ScaledObjectRef.Merge(m, src) +} +func (m *ScaledObjectRef) XXX_Size() int { + return xxx_messageInfo_ScaledObjectRef.Size(m) +} +func (m *ScaledObjectRef) XXX_DiscardUnknown() { + xxx_messageInfo_ScaledObjectRef.DiscardUnknown(m) +} + +var xxx_messageInfo_ScaledObjectRef proto.InternalMessageInfo + +func (m *ScaledObjectRef) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *ScaledObjectRef) GetNamespace() string { + if m != nil { + return m.Namespace + } + return "" +} + +type NewRequest struct { + ScaledObjectRef *ScaledObjectRef `protobuf:"bytes,1,opt,name=scaledObjectRef,proto3" json:"scaledObjectRef,omitempty"` + Metadata map[string]string `protobuf:"bytes,2,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *NewRequest) Reset() { *m = NewRequest{} } +func (m *NewRequest) String() string { return proto.CompactTextString(m) } +func (*NewRequest) ProtoMessage() {} +func (*NewRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{1} +} + +func (m *NewRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_NewRequest.Unmarshal(m, b) +} +func (m *NewRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_NewRequest.Marshal(b, m, deterministic) +} +func (m *NewRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_NewRequest.Merge(m, src) +} +func (m *NewRequest) XXX_Size() int { + return xxx_messageInfo_NewRequest.Size(m) +} +func (m *NewRequest) XXX_DiscardUnknown() { + xxx_messageInfo_NewRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_NewRequest proto.InternalMessageInfo + +func (m *NewRequest) GetScaledObjectRef() *ScaledObjectRef { + if m != nil { + return m.ScaledObjectRef + } + return nil +} + +func (m *NewRequest) GetMetadata() map[string]string { + if m != nil { + return m.Metadata + } + return nil +} + +type IsActiveResponse struct { + Result bool `protobuf:"varint,1,opt,name=result,proto3" json:"result,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *IsActiveResponse) Reset() { *m = IsActiveResponse{} } +func (m *IsActiveResponse) String() string { return proto.CompactTextString(m) } +func (*IsActiveResponse) ProtoMessage() {} +func (*IsActiveResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{2} +} + +func (m *IsActiveResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_IsActiveResponse.Unmarshal(m, b) +} +func (m *IsActiveResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_IsActiveResponse.Marshal(b, m, deterministic) +} +func (m *IsActiveResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_IsActiveResponse.Merge(m, src) +} +func (m *IsActiveResponse) XXX_Size() int { + return xxx_messageInfo_IsActiveResponse.Size(m) +} +func (m *IsActiveResponse) XXX_DiscardUnknown() { + xxx_messageInfo_IsActiveResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_IsActiveResponse proto.InternalMessageInfo + +func (m *IsActiveResponse) GetResult() bool { + if m != nil { + return m.Result + } + return false +} + +type GetMetricSpecResponse struct { + MetricSpecs []*MetricSpec `protobuf:"bytes,1,rep,name=metricSpecs,proto3" json:"metricSpecs,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetMetricSpecResponse) Reset() { *m = GetMetricSpecResponse{} } +func (m *GetMetricSpecResponse) String() string { return proto.CompactTextString(m) } +func (*GetMetricSpecResponse) ProtoMessage() {} +func (*GetMetricSpecResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{3} +} + +func (m *GetMetricSpecResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetMetricSpecResponse.Unmarshal(m, b) +} +func (m *GetMetricSpecResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetMetricSpecResponse.Marshal(b, m, deterministic) +} +func (m *GetMetricSpecResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetMetricSpecResponse.Merge(m, src) +} +func (m *GetMetricSpecResponse) XXX_Size() int { + return xxx_messageInfo_GetMetricSpecResponse.Size(m) +} +func (m *GetMetricSpecResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetMetricSpecResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetMetricSpecResponse proto.InternalMessageInfo + +func (m *GetMetricSpecResponse) GetMetricSpecs() []*MetricSpec { + if m != nil { + return m.MetricSpecs + } + return nil +} + +type MetricSpec struct { + MetricName string `protobuf:"bytes,1,opt,name=metricName,proto3" json:"metricName,omitempty"` + TargetSize int64 `protobuf:"varint,2,opt,name=targetSize,proto3" json:"targetSize,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MetricSpec) Reset() { *m = MetricSpec{} } +func (m *MetricSpec) String() string { return proto.CompactTextString(m) } +func (*MetricSpec) ProtoMessage() {} +func (*MetricSpec) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{4} +} + +func (m *MetricSpec) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MetricSpec.Unmarshal(m, b) +} +func (m *MetricSpec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MetricSpec.Marshal(b, m, deterministic) +} +func (m *MetricSpec) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetricSpec.Merge(m, src) +} +func (m *MetricSpec) XXX_Size() int { + return xxx_messageInfo_MetricSpec.Size(m) +} +func (m *MetricSpec) XXX_DiscardUnknown() { + xxx_messageInfo_MetricSpec.DiscardUnknown(m) +} + +var xxx_messageInfo_MetricSpec proto.InternalMessageInfo + +func (m *MetricSpec) GetMetricName() string { + if m != nil { + return m.MetricName + } + return "" +} + +func (m *MetricSpec) GetTargetSize() int64 { + if m != nil { + return m.TargetSize + } + return 0 +} + +type GetMetricsRequest struct { + ScaledObjectRef *ScaledObjectRef `protobuf:"bytes,1,opt,name=scaledObjectRef,proto3" json:"scaledObjectRef,omitempty"` + MetricName string `protobuf:"bytes,2,opt,name=metricName,proto3" json:"metricName,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetMetricsRequest) Reset() { *m = GetMetricsRequest{} } +func (m *GetMetricsRequest) String() string { return proto.CompactTextString(m) } +func (*GetMetricsRequest) ProtoMessage() {} +func (*GetMetricsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{5} +} + +func (m *GetMetricsRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetMetricsRequest.Unmarshal(m, b) +} +func (m *GetMetricsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetMetricsRequest.Marshal(b, m, deterministic) +} +func (m *GetMetricsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetMetricsRequest.Merge(m, src) +} +func (m *GetMetricsRequest) XXX_Size() int { + return xxx_messageInfo_GetMetricsRequest.Size(m) +} +func (m *GetMetricsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_GetMetricsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_GetMetricsRequest proto.InternalMessageInfo + +func (m *GetMetricsRequest) GetScaledObjectRef() *ScaledObjectRef { + if m != nil { + return m.ScaledObjectRef + } + return nil +} + +func (m *GetMetricsRequest) GetMetricName() string { + if m != nil { + return m.MetricName + } + return "" +} + +type GetMetricsResponse struct { + MetricValues []*MetricValue `protobuf:"bytes,1,rep,name=metricValues,proto3" json:"metricValues,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *GetMetricsResponse) Reset() { *m = GetMetricsResponse{} } +func (m *GetMetricsResponse) String() string { return proto.CompactTextString(m) } +func (*GetMetricsResponse) ProtoMessage() {} +func (*GetMetricsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{6} +} + +func (m *GetMetricsResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_GetMetricsResponse.Unmarshal(m, b) +} +func (m *GetMetricsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_GetMetricsResponse.Marshal(b, m, deterministic) +} +func (m *GetMetricsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_GetMetricsResponse.Merge(m, src) +} +func (m *GetMetricsResponse) XXX_Size() int { + return xxx_messageInfo_GetMetricsResponse.Size(m) +} +func (m *GetMetricsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_GetMetricsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_GetMetricsResponse proto.InternalMessageInfo + +func (m *GetMetricsResponse) GetMetricValues() []*MetricValue { + if m != nil { + return m.MetricValues + } + return nil +} + +type MetricValue struct { + MetricName string `protobuf:"bytes,1,opt,name=metricName,proto3" json:"metricName,omitempty"` + MetricValue int64 `protobuf:"varint,2,opt,name=metricValue,proto3" json:"metricValue,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *MetricValue) Reset() { *m = MetricValue{} } +func (m *MetricValue) String() string { return proto.CompactTextString(m) } +func (*MetricValue) ProtoMessage() {} +func (*MetricValue) Descriptor() ([]byte, []int) { + return fileDescriptor_5d6e95065d56f393, []int{7} +} + +func (m *MetricValue) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_MetricValue.Unmarshal(m, b) +} +func (m *MetricValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_MetricValue.Marshal(b, m, deterministic) +} +func (m *MetricValue) XXX_Merge(src proto.Message) { + xxx_messageInfo_MetricValue.Merge(m, src) +} +func (m *MetricValue) XXX_Size() int { + return xxx_messageInfo_MetricValue.Size(m) +} +func (m *MetricValue) XXX_DiscardUnknown() { + xxx_messageInfo_MetricValue.DiscardUnknown(m) +} + +var xxx_messageInfo_MetricValue proto.InternalMessageInfo + +func (m *MetricValue) GetMetricName() string { + if m != nil { + return m.MetricName + } + return "" +} + +func (m *MetricValue) GetMetricValue() int64 { + if m != nil { + return m.MetricValue + } + return 0 +} + +func init() { + proto.RegisterType((*ScaledObjectRef)(nil), "externalscaler.ScaledObjectRef") + proto.RegisterType((*NewRequest)(nil), "externalscaler.NewRequest") + proto.RegisterMapType((map[string]string)(nil), "externalscaler.NewRequest.MetadataEntry") + proto.RegisterType((*IsActiveResponse)(nil), "externalscaler.IsActiveResponse") + proto.RegisterType((*GetMetricSpecResponse)(nil), "externalscaler.GetMetricSpecResponse") + proto.RegisterType((*MetricSpec)(nil), "externalscaler.MetricSpec") + proto.RegisterType((*GetMetricsRequest)(nil), "externalscaler.GetMetricsRequest") + proto.RegisterType((*GetMetricsResponse)(nil), "externalscaler.GetMetricsResponse") + proto.RegisterType((*MetricValue)(nil), "externalscaler.MetricValue") +} + +func init() { proto.RegisterFile("proto/externalscaler.proto", fileDescriptor_5d6e95065d56f393) } + +var fileDescriptor_5d6e95065d56f393 = []byte{ + // 485 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x53, 0x4d, 0x6f, 0xd3, 0x40, + 0x10, 0x8d, 0x63, 0x5a, 0xa5, 0x13, 0xfa, 0xc1, 0x08, 0xaa, 0xc8, 0x45, 0x10, 0x56, 0x42, 0x8a, + 0x38, 0x38, 0x52, 0xb8, 0x20, 0x8a, 0x84, 0xa0, 0x44, 0xa8, 0x12, 0x4d, 0xa4, 0x8d, 0x52, 0x89, + 0xe3, 0xc6, 0x9d, 0x46, 0x01, 0x27, 0x36, 0xde, 0x75, 0x4b, 0x38, 0xf0, 0x2b, 0xf8, 0x75, 0xfc, + 0x1a, 0xe4, 0xf5, 0xf7, 0xaa, 0x21, 0x5c, 0x38, 0xd9, 0xfb, 0xe6, 0xcd, 0xec, 0xbc, 0x37, 0xb3, + 0xe0, 0x84, 0x51, 0xa0, 0x82, 0x3e, 0x7d, 0x57, 0x14, 0xad, 0x84, 0x2f, 0x3d, 0xe1, 0x53, 0xe4, + 0x6a, 0x10, 0x0f, 0xea, 0xa8, 0x73, 0x32, 0x0f, 0x82, 0xb9, 0x4f, 0x7d, 0x1d, 0x9d, 0xc5, 0xd7, + 0x7d, 0x5a, 0x86, 0x6a, 0x9d, 0x92, 0xd9, 0x19, 0x1c, 0x4e, 0x12, 0xda, 0xd5, 0x78, 0xf6, 0x85, + 0x3c, 0xc5, 0xe9, 0x1a, 0x11, 0xee, 0xad, 0xc4, 0x92, 0x3a, 0x56, 0xd7, 0xea, 0xed, 0x71, 0xfd, + 0x8f, 0x8f, 0x61, 0x2f, 0xf9, 0xca, 0x50, 0x78, 0xd4, 0x69, 0xea, 0x40, 0x09, 0xb0, 0xdf, 0x16, + 0xc0, 0x88, 0x6e, 0x39, 0x7d, 0x8b, 0x49, 0x2a, 0x3c, 0x87, 0x43, 0x59, 0xaf, 0xa9, 0x6b, 0xb5, + 0x07, 0x4f, 0x5d, 0xa3, 0x61, 0xe3, 0x6a, 0x6e, 0xe6, 0xe1, 0x07, 0x68, 0x2d, 0x49, 0x89, 0x2b, + 0xa1, 0x44, 0xa7, 0xd9, 0xb5, 0x7b, 0xed, 0x41, 0xcf, 0xac, 0x51, 0x5e, 0xec, 0x5e, 0x64, 0xd4, + 0xe1, 0x4a, 0x45, 0x6b, 0x5e, 0x64, 0x3a, 0xa7, 0xb0, 0x5f, 0x0b, 0xe1, 0x11, 0xd8, 0x5f, 0x69, + 0x9d, 0x29, 0x4c, 0x7e, 0xf1, 0x21, 0xec, 0xdc, 0x08, 0x3f, 0xce, 0xc5, 0xa5, 0x87, 0xd7, 0xcd, + 0x57, 0x16, 0x7b, 0x01, 0x47, 0xe7, 0xf2, 0x9d, 0xa7, 0x16, 0x37, 0xc4, 0x49, 0x86, 0xc1, 0x4a, + 0x12, 0x1e, 0xc3, 0x6e, 0x44, 0x32, 0xf6, 0x95, 0x2e, 0xd1, 0xe2, 0xd9, 0x89, 0x4d, 0xe1, 0xd1, + 0x47, 0x52, 0x17, 0xa4, 0xa2, 0x85, 0x37, 0x09, 0xc9, 0x2b, 0x12, 0xde, 0x40, 0x7b, 0x59, 0xa0, + 0xb2, 0x63, 0x69, 0x29, 0x8e, 0x29, 0xa5, 0x92, 0x58, 0xa5, 0xb3, 0x4f, 0x00, 0x65, 0x08, 0x9f, + 0x00, 0xa4, 0xc1, 0x51, 0x39, 0xa5, 0x0a, 0x92, 0xc4, 0x95, 0x88, 0xe6, 0xa4, 0x26, 0x8b, 0x1f, + 0xa9, 0x1e, 0x9b, 0x57, 0x10, 0xf6, 0x13, 0x1e, 0x14, 0x4d, 0xca, 0xff, 0x30, 0xb3, 0x7a, 0x7f, + 0x4d, 0xb3, 0x3f, 0x36, 0x05, 0xac, 0xde, 0x9f, 0x39, 0xf4, 0x16, 0xee, 0xa7, 0x9c, 0xcb, 0xc4, + 0xf9, 0xdc, 0xa2, 0x93, 0xbb, 0x2d, 0xd2, 0x1c, 0x5e, 0x4b, 0x60, 0x63, 0x68, 0x57, 0x82, 0x5b, + 0x5d, 0xea, 0xe6, 0x13, 0xb9, 0x2c, 0xc6, 0x6e, 0xf3, 0x2a, 0x34, 0xf8, 0x65, 0xc3, 0xc1, 0x30, + 0xbb, 0x5d, 0x8b, 0x8e, 0xf0, 0x14, 0xec, 0x11, 0xdd, 0xa2, 0xb3, 0x79, 0x07, 0x9d, 0x63, 0x37, + 0x7d, 0x6e, 0x6e, 0xfe, 0xdc, 0xdc, 0x61, 0xf2, 0xdc, 0x58, 0x03, 0xc7, 0xd0, 0xca, 0x17, 0x09, + 0xb7, 0xb9, 0xea, 0x74, 0x4d, 0x82, 0xb9, 0x83, 0xac, 0x81, 0x9f, 0x61, 0xbf, 0xb6, 0x6d, 0xdb, + 0xab, 0x3e, 0x37, 0x09, 0x77, 0x6e, 0x2b, 0x6b, 0xe0, 0x14, 0xa0, 0x9c, 0x11, 0x3e, 0xdb, 0x98, + 0x96, 0xef, 0x8f, 0xc3, 0xfe, 0x46, 0x29, 0xca, 0xbe, 0x87, 0x9d, 0x33, 0x3f, 0x90, 0xff, 0xa0, + 0x7f, 0xa3, 0x8d, 0xb3, 0x5d, 0x8d, 0xbc, 0xfc, 0x13, 0x00, 0x00, 0xff, 0xff, 0x40, 0x76, 0xa8, + 0xba, 0x03, 0x05, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// ExternalScalerClient is the client API for ExternalScaler service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type ExternalScalerClient interface { + New(ctx context.Context, in *NewRequest, opts ...grpc.CallOption) (*empty.Empty, error) + IsActive(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*IsActiveResponse, error) + GetMetricSpec(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*GetMetricSpecResponse, error) + GetMetrics(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*GetMetricsResponse, error) + Close(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*empty.Empty, error) +} + +type externalScalerClient struct { + cc *grpc.ClientConn +} + +func NewExternalScalerClient(cc *grpc.ClientConn) ExternalScalerClient { + return &externalScalerClient{cc} +} + +func (c *externalScalerClient) New(ctx context.Context, in *NewRequest, opts ...grpc.CallOption) (*empty.Empty, error) { + out := new(empty.Empty) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/New", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *externalScalerClient) IsActive(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*IsActiveResponse, error) { + out := new(IsActiveResponse) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/IsActive", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *externalScalerClient) GetMetricSpec(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*GetMetricSpecResponse, error) { + out := new(GetMetricSpecResponse) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/GetMetricSpec", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *externalScalerClient) GetMetrics(ctx context.Context, in *GetMetricsRequest, opts ...grpc.CallOption) (*GetMetricsResponse, error) { + out := new(GetMetricsResponse) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/GetMetrics", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *externalScalerClient) Close(ctx context.Context, in *ScaledObjectRef, opts ...grpc.CallOption) (*empty.Empty, error) { + out := new(empty.Empty) + err := c.cc.Invoke(ctx, "/externalscaler.ExternalScaler/Close", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ExternalScalerServer is the server API for ExternalScaler service. +type ExternalScalerServer interface { + New(context.Context, *NewRequest) (*empty.Empty, error) + IsActive(context.Context, *ScaledObjectRef) (*IsActiveResponse, error) + GetMetricSpec(context.Context, *ScaledObjectRef) (*GetMetricSpecResponse, error) + GetMetrics(context.Context, *GetMetricsRequest) (*GetMetricsResponse, error) + Close(context.Context, *ScaledObjectRef) (*empty.Empty, error) +} + +// UnimplementedExternalScalerServer can be embedded to have forward compatible implementations. +type UnimplementedExternalScalerServer struct { +} + +func (*UnimplementedExternalScalerServer) New(ctx context.Context, req *NewRequest) (*empty.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method New not implemented") +} +func (*UnimplementedExternalScalerServer) IsActive(ctx context.Context, req *ScaledObjectRef) (*IsActiveResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method IsActive not implemented") +} +func (*UnimplementedExternalScalerServer) GetMetricSpec(ctx context.Context, req *ScaledObjectRef) (*GetMetricSpecResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMetricSpec not implemented") +} +func (*UnimplementedExternalScalerServer) GetMetrics(ctx context.Context, req *GetMetricsRequest) (*GetMetricsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetMetrics not implemented") +} +func (*UnimplementedExternalScalerServer) Close(ctx context.Context, req *ScaledObjectRef) (*empty.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method Close not implemented") +} + +func RegisterExternalScalerServer(s *grpc.Server, srv ExternalScalerServer) { + s.RegisterService(&_ExternalScaler_serviceDesc, srv) +} + +func _ExternalScaler_New_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NewRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).New(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/New", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).New(ctx, req.(*NewRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ExternalScaler_IsActive_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ScaledObjectRef) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).IsActive(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/IsActive", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).IsActive(ctx, req.(*ScaledObjectRef)) + } + return interceptor(ctx, in, info, handler) +} + +func _ExternalScaler_GetMetricSpec_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ScaledObjectRef) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).GetMetricSpec(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/GetMetricSpec", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).GetMetricSpec(ctx, req.(*ScaledObjectRef)) + } + return interceptor(ctx, in, info, handler) +} + +func _ExternalScaler_GetMetrics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetMetricsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).GetMetrics(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/GetMetrics", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).GetMetrics(ctx, req.(*GetMetricsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ExternalScaler_Close_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ScaledObjectRef) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ExternalScalerServer).Close(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/externalscaler.ExternalScaler/Close", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ExternalScalerServer).Close(ctx, req.(*ScaledObjectRef)) + } + return interceptor(ctx, in, info, handler) +} + +var _ExternalScaler_serviceDesc = grpc.ServiceDesc{ + ServiceName: "externalscaler.ExternalScaler", + HandlerType: (*ExternalScalerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "New", + Handler: _ExternalScaler_New_Handler, + }, + { + MethodName: "IsActive", + Handler: _ExternalScaler_IsActive_Handler, + }, + { + MethodName: "GetMetricSpec", + Handler: _ExternalScaler_GetMetricSpec_Handler, + }, + { + MethodName: "GetMetrics", + Handler: _ExternalScaler_GetMetrics_Handler, + }, + { + MethodName: "Close", + Handler: _ExternalScaler_Close_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/externalscaler.proto", +} diff --git a/metrics-provider/externalscaler/proto/externalscaler.proto b/metrics-provider/externalscaler/proto/externalscaler.proto new file mode 100644 index 0000000..9012060 --- /dev/null +++ b/metrics-provider/externalscaler/proto/externalscaler.proto @@ -0,0 +1,50 @@ +syntax = "proto3"; + +package externalscaler; + +import "google/protobuf/empty.proto"; + +service ExternalScaler { + rpc New(NewRequest) returns (google.protobuf.Empty) {} + rpc IsActive(ScaledObjectRef) returns (IsActiveResponse) {} + rpc GetMetricSpec(ScaledObjectRef) returns (GetMetricSpecResponse) {} + rpc GetMetrics(GetMetricsRequest) returns (GetMetricsResponse) {} + rpc Close(ScaledObjectRef) returns (google.protobuf.Empty) {} +} + +message ScaledObjectRef { + string name = 1; + string namespace = 2; +} + +message NewRequest { + ScaledObjectRef scaledObjectRef = 1; + map metadata = 2; +} + +message IsActiveResponse { + bool result = 1; +} + +message GetMetricSpecResponse { + repeated MetricSpec metricSpecs = 1; +} + +message MetricSpec { + string metricName = 1; + int64 targetSize = 2; +} + +message GetMetricsRequest { + ScaledObjectRef scaledObjectRef = 1; + string metricName = 2; +} + +message GetMetricsResponse { + repeated MetricValue metricValues = 1; +} + +message MetricValue { + string metricName = 1; + int64 metricValue = 2; +} \ No newline at end of file diff --git a/metrics-provider/go.mod b/metrics-provider/go.mod new file mode 100644 index 0000000..a2bf8d1 --- /dev/null +++ b/metrics-provider/go.mod @@ -0,0 +1,10 @@ +module github.com/balchua/artemis-ext-scaler + +go 1.13 + +require ( + github.com/golang/protobuf v1.3.2 + github.com/nats-io/stan.go v0.5.0 // indirect + github.com/sirupsen/logrus v1.4.2 + google.golang.org/grpc v1.24.0 +) diff --git a/metrics-provider/go.sum b/metrics-provider/go.sum new file mode 100644 index 0000000..56f4496 --- /dev/null +++ b/metrics-provider/go.sum @@ -0,0 +1,46 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nats-io/stan.go v0.5.0 h1:ZaSPMb6jnDXsSlOACynJrUiB3Evleg3ZyyX+rnf3TlQ= +github.com/nats-io/stan.go v0.5.0/go.mod h1:dYqB+vMN3C2F9pT1FRQpg9eHbjPj6mP0yYuyBNuXHZE= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/metrics-provider/server.go b/metrics-provider/server.go new file mode 100644 index 0000000..36a3d01 --- /dev/null +++ b/metrics-provider/server.go @@ -0,0 +1,187 @@ +package main + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "net" + "net/http" + "strconv" + "time" + + pb "github.com/balchua/artemis-ext-scaler/externalscaler/proto" + "github.com/golang/protobuf/ptypes/empty" + log "github.com/sirupsen/logrus" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +var ( + port int + artemisURL string + artemisBrokerName string + artemisAddress string + artemisQueueName string + userName string + password string + metricName string + targetSize int +) + +type monitoring struct { + Request string `json:"request"` + MsgCount int64 `json:"value"` + Status int `json:"status"` + Timestamp int64 `json:"timestamp"` +} + +type requestInfo struct { + Mbean string `json:"mbean"` + Attribute string `json:"attribute"` + Type string `json:"type"` +} + +type externalScalerServer struct { + scaledObjectRef map[string][]*pb.ScaledObjectRef +} + +func init() { + + // Only log the warning severity or above. + log.SetLevel(log.InfoLevel) +} + +func getArtemisEndpoint() string { + return artemisURL + "/console/jolokia/read/org.apache.activemq.artemis" + ":broker=" + "\"" + + artemisBrokerName + "\"" + ",component=addresses,address=" + "\"" + + artemisAddress + "\"" + ",subcomponent=queues,routing-type=\"anycast\",queue=\"" + + artemisQueueName + "\"" + "/MessageCount" +} + +// NewRequest - Do nothing here +func (s *externalScalerServer) New(ctx context.Context, newRequest *pb.NewRequest) (*empty.Empty, error) { + out := new(empty.Empty) + + size, err := strconv.Atoi(newRequest.Metadata["queueLength"]) + + if err != nil { + targetSize = 10 + } else { + targetSize = size + } + + artemisAddress = newRequest.Metadata["brokerAddress"] + artemisQueueName = newRequest.Metadata["queueName"] + metricName = artemisBrokerName + "-" + artemisAddress + "-" + artemisQueueName + return out, nil +} + +// Close +func (s *externalScalerServer) Close(ctx context.Context, scaledObjectRef *pb.ScaledObjectRef) (*empty.Empty, error) { + out := new(empty.Empty) + + return out, nil +} + +// IsActive +func (s *externalScalerServer) IsActive(ctx context.Context, in *pb.ScaledObjectRef) (*pb.IsActiveResponse, error) { + out := new(pb.IsActiveResponse) + out.Result = (s.getMessageCount() > 0) + return out, nil +} + +func (s *externalScalerServer) GetMetricSpec(ctx context.Context, in *pb.ScaledObjectRef) (*pb.GetMetricSpecResponse, error) { + log.Info("Getting Metric Spec") + out := new(pb.GetMetricSpecResponse) + + m := new(pb.MetricSpec) + m.MetricName = metricName + m.TargetSize = int64(targetSize) + + out.MetricSpecs = make([]*pb.MetricSpec, 1) + + out.MetricSpecs[0] = m + log.Infof("Metrics Name: %s \n Metrics TargetSize: %d\n", out.MetricSpecs[0].MetricName, out.MetricSpecs[0].TargetSize) + + return out, nil +} + +func (s *externalScalerServer) getMessageCount() int64 { + var messageCount int64 + var monitoringInfo *monitoring + messageCount = 0 + + log.Info("getting the message count") + + client := &http.Client{ + Timeout: time.Second * 3, + } + url := getArtemisEndpoint() + log.Infof("URL: %s", url) + req, err := http.NewRequest("GET", url, nil) + req.SetBasicAuth("artemis", "artemis") + if err != nil { + log.Errorf("Error while accessing ActiveMQ: %s", err) + return 0 + } + resp, err := client.Do(req) + if err != nil { + log.Errorf("Error while accessing ActiveMQ: %s", err) + return 0 + } + + defer resp.Body.Close() + + json.NewDecoder(resp.Body).Decode(&monitoringInfo) + if resp.StatusCode == 200 && monitoringInfo.Status == 200 { + messageCount = monitoringInfo.MsgCount + } + log.Infof("Total messages: %d", messageCount) + return messageCount +} + +func (s *externalScalerServer) GetMetrics(ctx context.Context, in *pb.GetMetricsRequest) (*pb.GetMetricsResponse, error) { + + messageCount := s.getMessageCount() + + m := new(pb.MetricValue) + m.MetricName = metricName + m.MetricValue = messageCount + + out := new(pb.GetMetricsResponse) + + out.MetricValues = make([]*pb.MetricValue, 1) + out.MetricValues[0] = m + + return out, nil +} + +func newServer() *externalScalerServer { + s := &externalScalerServer{} + + return s +} + +func main() { + flag.IntVar(&port, "port", 10000, "The server port") + flag.StringVar(&artemisURL, "url", "http://localhost:8161", "The artemis server url") + flag.StringVar(&artemisBrokerName, "broker", "artemis-activemq", "The artemis broker name") + flag.StringVar(&userName, "user", "artemis", "The artemis broker address") + flag.StringVar(&password, "password", "artemis", "The artemis broker address") + + flag.Parse() + + fmt.Printf("Port: %d\n", port) + fmt.Printf("URL: %s\n", artemisURL) + lis, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", 5050)) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + + var opts []grpc.ServerOption + grpcServer := grpc.NewServer(opts...) + reflection.Register(grpcServer) + pb.RegisterExternalScalerServer(grpcServer, newServer()) + grpcServer.Serve(lis) +} diff --git a/producer/pom.xml b/producer/pom.xml new file mode 100644 index 0000000..5792dfc --- /dev/null +++ b/producer/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + artemis-producer + jar + producer + org.bal.app + 0.0.1 + SpringBootArtemisProducer + + + org.springframework.boot + spring-boot-starter-parent + 2.1.6.RELEASE + + + UTF-8 + UTF-8 + 11 + 1.4.0 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework + spring-jms + + + + org.springframework.boot + spring-boot-starter-artemis + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + + org.bal.starter.App + ZIP + + spring-boot-maven-plugin + + + + repackage + + + + + + + + maven-resources-plugin + ${maven-resources-plugin.version} + + + filter-dockerfile + process-resources + + copy-resources + + + ${project.build.directory} + + + src/main/docker + true + + + + + + + + + com.google.cloud.tools + jib-maven-plugin + ${jib-version} + + true + + adoptopenjdk/openjdk11:jdk-11.0.3_7-debian-slim + + + true + + -Djava.security.egd=file:/dev/./urandom + + + + balchu/${project.artifactId}:${project.version} + + + + + + + + \ No newline at end of file diff --git a/producer/src/main/java/org/bal/config/ProducerConfiguration.java b/producer/src/main/java/org/bal/config/ProducerConfiguration.java new file mode 100644 index 0000000..45ec026 --- /dev/null +++ b/producer/src/main/java/org/bal/config/ProducerConfiguration.java @@ -0,0 +1,16 @@ +package org.bal.config; + +import org.bal.producer.Producer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jms.annotation.EnableJms; + +@Configuration +@EnableJms +public class ProducerConfiguration { + + @Bean + public Producer sender() { + return new Producer(); + } +} \ No newline at end of file diff --git a/producer/src/main/java/org/bal/producer/Producer.java b/producer/src/main/java/org/bal/producer/Producer.java new file mode 100644 index 0000000..a3e24ad --- /dev/null +++ b/producer/src/main/java/org/bal/producer/Producer.java @@ -0,0 +1,20 @@ +package org.bal.producer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jms.core.JmsTemplate; + +public class Producer { + + private static final Logger LOGGER = + LoggerFactory.getLogger(Producer.class); + + @Autowired + private JmsTemplate jmsTemplate; + + public void send(String message) { + LOGGER.info("sending message='{}'", message); + jmsTemplate.convertAndSend("test", message); + } +} \ No newline at end of file diff --git a/producer/src/main/java/org/bal/starter/App.java b/producer/src/main/java/org/bal/starter/App.java new file mode 100644 index 0000000..0f759b6 --- /dev/null +++ b/producer/src/main/java/org/bal/starter/App.java @@ -0,0 +1,30 @@ +package org.bal.starter; + +import org.bal.config.ProducerConfiguration; +import org.bal.producer.Producer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import static java.lang.Thread.sleep; + +@SpringBootApplication(scanBasePackageClasses = {ProducerConfiguration.class}, scanBasePackages = "org.bal") +public class App implements CommandLineRunner { + + @Autowired + private Producer producer; + + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } + + + @Override + public void run(String... args) throws Exception { + for (int i = 0; i < 1000; i++){ + producer.send("Message is: " + System.currentTimeMillis()); + sleep(200); + } + } +} \ No newline at end of file diff --git a/producer/src/main/resources/application.yml b/producer/src/main/resources/application.yml new file mode 100644 index 0000000..9ddcd80 --- /dev/null +++ b/producer/src/main/resources/application.yml @@ -0,0 +1,7 @@ +spring: + artemis: + mode: native + host: ${ARTEMIS_SERVER_HOST:10.152.183.87} + port: ${ARTEMIS_SERVER_PORT:61616} + user: ${ARTEMIS_USERNAME:artemis} + password: ${ARTEMIS_PASSWORD:artemis} \ No newline at end of file diff --git a/skaffold.yaml b/skaffold.yaml new file mode 100644 index 0000000..fee23b9 --- /dev/null +++ b/skaffold.yaml @@ -0,0 +1,58 @@ +apiVersion: skaffold/v1beta15 +kind: Config +profiles: +- name: metrics-provider-local + build: + insecureRegistries: #Use this for local registry. such as microk8s registry. + - 192.168.1.12:32000 + artifacts: + - image: 192.168.1.12:32000/artemis-ext-scaler + context: ./metrics-provider + kaniko: + dockerfile: Dockerfile + buildContext: + localDir: {} + cache: + repo: 192.168.1.12:32000/artemis-ext-scaler + cluster: + dockerConfig: + secretName: regcred + namespace: artemis + deploy: + kubectl: + manifests: + - k8s-manifest/artemis/deployment.yaml + +- name: metrics-provider + build: + artifacts: + - image: balchu/artemis-ext-scaler + context: ./metrics-provider + kaniko: + dockerfile: Dockerfile + buildContext: + localDir: {} + cache: + repo: balchu/artemis-ext-scaler + cluster: + dockerConfig: + secretName: regcred + namespace: artemis + deploy: + kubectl: + manifests: + - k8s-manifest/artemis/deployment.yaml + +- name: consumer + build: + artifacts: + - image: 192.168.1.12:32000/artemis-consumer + context: ./consumer + jib: {} + local: + push: true + useDockerCLI: false + deploy: + kubectl: + manifests: + - k8s-manifest/consumer-deployment.yaml