Code Monkey home page Code Monkey logo

dataplaneapi's Introduction

HAProxy

HAProxy Data Plane API

Contributors License

Data Plane API is a sidecar process that runs next to HAProxy and provides API endpoints for managing HAProxy. It requires HAProxy version 1.9.0 or higher.

Building the Data Plane API

In order to build the Data Plane API you need Go installed on your system with go modules support enabled, and execute the following steps:

1. Clone dataplaneapi repository

git clone https://github.com/haproxytech/dataplaneapi.git

2. Run make build:

make build

3. You can find the built binary in /build directory. TEST

Running the Data Plane API

Basic usage:

Usage:
  dataplaneapi [OPTIONS]

API for editing and managing haproxy instances

Application Options:
      --scheme=                                       the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec
      --cleanup-timeout=                              grace period for which to wait before killing idle connections (default: 10s)
      --graceful-timeout=                             grace period for which to wait before shutting down the server (default: 15s)
      --max-header-size=                              controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request
                                                      body. (default: 1MiB)
      --socket-path=                                  the unix socket to listen on (default: /var/run/data-plane.sock)
      --host=                                         the IP to listen on (default: localhost) [$HOST]
      --port=                                         the port to listen on for insecure connections, defaults to a random value [$PORT]
      --listen-limit=                                 limit the number of outstanding requests
      --keep-alive=                                   sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download) (default: 3m)
      --read-timeout=                                 maximum duration before timing out read of the request (default: 30s)
      --write-timeout=                                maximum duration before timing out write of the response (default: 60s)
      --tls-host=                                     the IP to listen on for tls, when not specified it's the same as --host [$TLS_HOST]
      --tls-port=                                     the port to listen on for secure connections, defaults to a random value [$TLS_PORT]
      --tls-certificate=                              the certificate to use for secure connections [$TLS_CERTIFICATE]
      --tls-key=                                      the private key to use for secure connections [$TLS_PRIVATE_KEY]
      --tls-ca=                                       the certificate authority file to be used with mutual tls auth [$TLS_CA_CERTIFICATE]
      --tls-listen-limit=                             limit the number of outstanding requests
      --tls-keep-alive=                               sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)
      --tls-read-timeout=                             maximum duration before timing out read of the request
      --tls-write-timeout=                            maximum duration before timing out write of the response
      --uid                                           user id value to set on start
      --gid                                           group id value to set on start

HAProxy options:
  -c, --config-file=                                  Path to the haproxy configuration file (default: /etc/haproxy/haproxy.cfg)
  -u, --userlist=                                     Userlist in HAProxy configuration to use for API Basic Authentication (default: controller)
  -b, --haproxy-bin=                                  Path to the haproxy binary file (default: haproxy)
  -d, --reload-delay=                                 Minimum delay between two reloads (in s) (default: 5)
  -r, --reload-cmd=                                   Reload command
  -s, --restart-cmd=                                  Restart command
      --reload-retention=                             Reload retention in days, every older reload id will be deleted (default: 1)
  -t, --transaction-dir=                              Path to the transaction directory (default: /tmp/haproxy)
  -n, --backups-number=                               Number of backup configuration files you want to keep, stored in the config dir with version number suffix (default: 0)
      --backups-dir=                                  Path to directory in which to place backup files
  -m, --master-runtime=                               Path to the master Runtime API socket
  -i, --show-system-info                              Show system info on info endpoint
  -f=                                                 Path to the dataplane configuration file (default: /etc/haproxy/dataplaneapi.yaml)
      --userlist-file=                                Path to the dataplaneapi userlist file. By default userlist is read from HAProxy conf. When specified userlist would be read from this file
      --fid=                                          Path to file that will dataplaneapi use to write its id (not a pid) that was given to him after joining a cluster
  -p, --maps-dir=                                     Path to directory of map files managed by dataplane (default: /etc/haproxy/maps)
      --ssl-certs-dir=                                Path to SSL certificates directory (default: /etc/haproxy/ssl)
      --update-map-files                              Flag used for syncing map files with runtime maps values
      --update-map-files-period=                      Elapsed time in seconds between two maps syncing operations (default: 10)
      --cluster-tls-dir=                              Path where cluster tls certificates will be stored. Defaults to same directory as dataplane configuration file
      --spoe-dir=                                     Path to SPOE directory. (default: /etc/haproxy/spoe)
      --spoe-transaction-dir=                         Path to the SPOE transaction directory (default: /tmp/spoe-haproxy)
      --master-worker-mode                            Flag to enable helpers when running within HAProxy
      --max-open-transactions=                        Limit for active transaction in pending state (default: 20)
      --validate-cmd=                                 Executes a custom command to perform the HAProxy configuration check
      --disable-inotify                               Disables inotify watcher watcher for the configuration file
      --pid-file=                                     Path to file that will dataplaneapi use to write its pid
      --debug-socket-path=                            Unix socket path for the debugging command socket
Logging options:
      --log-to=[stdout|file|syslog]                   Log target, can be stdout, file, or syslog (default: stdout)
      --log-file=                                     Location of the log file (default: /var/log/dataplaneapi/dataplaneapi.log)
      --log-level=[trace|debug|info|warning|error]    Logging level (default: warning)
      --log-format=[text|JSON]                        Logging format (default: text)
      --apache-common-log-format=                     Apache Common Log Format to format the access log entries (default: %h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i" %{us}T)

Syslog options:
      --syslog-address=                               Syslog address (with port declaration in case of TCP type) where logs should be forwarded: accepting socket path in case of unix or unixgram
      --syslog-protocol=[tcp|tcp4|tcp6|unix|unixgram] Syslog server protocol (default: tcp)
      --syslog-tag=                                   String to tag the syslog messages (default: dataplaneapi)
      --syslog-level=                                 Define the required syslog messages level, allowed values: debug|info|notice|warning|error|critical|alert|emergency  (default: debug)
      --syslog-facility=                              Define the Syslog facility number, allowed values: kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|authpriv|ftp|local0|local1|local2|local3|local4|local5|local6|local7
                                                      (default: local0)

Show version:
  -v, --version                                       Version and build information

Help Options:
  -h, --help                                          Show this help message

Beside those options, everything can be defined in side of configuration file. See configuration file

Example

You can test it by simply running:

./dataplaneapi --port 5555 -b /usr/sbin/haproxy -c /etc/haproxy/haproxy.cfg  -d 5 -r "service haproxy reload" -s "service haproxy restart" -u dataplaneapi -t /tmp/haproxy

Dataplaneapi will require write permissions to the haproxy configuration file and the directories containing additional managed files (maps, ssl, spoe). The default locations can be overriden with command-line options. Test it out with curl, note that you need user/pass combination setup in HAProxy userlist in haproxy configuration (in above example: /etc/haproxy/haproxy.cfg, userlist controller):

curl -u <user>:<pass> -H "Content-Type: application/json" "http://127.0.0.1:5555/v2/"

If you are using secure passwords, supported algorithms are: md5, sha-256 and sha-512.

Using the Data Plane API

For more docs how to use the Data Plane API check our documentation

Alternatively, dataplaneapi serves its own interactive documentation relevant for the current build on the /v2/docs uri. Just point your browser to the host/port dataplane was started with (i.e. http://localhost:5555/v2/docs)

Service Discovery

Check the documentation in the README.

Command socket for debugging purpose

Check the documentation in the README.

Contributing

If you wish to contribute to this project please check Contributing Guide

dataplaneapi's People

Contributors

aiharos avatar amelhusic avatar binlab avatar bmcustodio avatar clwluvw avatar daniel-corbett avatar dkorunic avatar dupondje avatar dvrkps avatar geodimm avatar georgijd-form3 avatar gitforbit avatar gorangalinec avatar hdurand0710 avatar jaredcurtis avatar kashifmin avatar mjuraga avatar oktalz avatar oliwer avatar pierresouchay avatar piotrolchawa-f3 avatar prometherion avatar rmaticevic avatar rubycut avatar schegi avatar vgramer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dataplaneapi's Issues

Error when quering backends

Hi,
We are receiving this error when calling:

curl -X GET --user admin:admin http://haproxy.domain.de:5555/v1/services/haproxy/configuration/backends

For the frontend works fine. We are running haproxy 2.0.1 and latest dataplaneapi binary.

time="2019-07-10T16:46:25+02:00" level=error msg="Panic runtime error: invalid memory address or nil pointer dereference" stack_trace="\n/usr/local/go/src/runtime/panic.go:81 panicmem\n/home/mjuraga/projects/go/pkg/mod/github.com/haproxytech/[email protected]/configuration/configuration.go:338 (*Client).parseField\n/home/mjuraga/projects/go/pkg/mod/github.com/haproxytech/[email protected]/configuration/configuration.go:271 (*Client).parseSection\n/home/mjuraga/projects/go/pkg/mod/github.com/haproxytech/[email protected]/configuration/backend.go:42 (*Client).GetBackends\n/home/mjuraga/projects/go/src/github.com/haproxytech/dataplaneapi/handlers/backend.go:160 (*GetBackendsHandlerImpl).Handle\n/home/mjuraga/projects/go/src/github.com/haproxytech/dataplaneapi/operations/backend/get_backends.go:90 (*GetBackends).ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/operation.go:28 NewOperationExecutor.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/router.go:76 NewRouter.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/redoc.go:72 Redoc.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/spec.go:46 Spec.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/src/github.com/haproxytech/dataplaneapi/adapters/adapters.go:151 RecoverMiddleware.func1.1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/rs/[email protected]/cors.go:207 (*Cors).Handler.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/src/github.com/haproxytech/dataplaneapi/adapters/adapters.go:165 LoggingMiddleware.func1.1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/usr/local/go/src/net/http/server.go:2774 serverHandler.ServeHTTP\n/usr/local/go/src/net/http/server.go:1878 (*conn).serve\n/usr/local/go/src/runtime/asm_amd64.s:1337 goexit"

Can't use "kill -SIGUSR2 1" in docker

I run a HAProxy with dataplaneapi in docker container on MacOS and use the command
--reload-cmd "kill -SIGUSR2 1" to do reload, but it doesn't work , the error message is exec: \"kill\": executable file not found in $PATH ,

so I change the cmd to "/bin/bash -c kill -SIGUSR2 1" , it still get the error: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]

I also tried "/bin/bash -c 'kill -SIGUSR2 1'" , turned out to be: -SIGUSR2: -c: line 0: unexpected EOF while looking for matching ``''

so how can I do reload cmd in docker?

the docker images is based on haproxy:2.0.5

Add support for multiple configuration files

This is a feature request.

We use multiple configuration files to keep our HAProxy configuration layout less cluttered. We start haproxy like so:

/usr/bin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d/

All the files in /etc/haproxy/conf.d/ are then loaded in lexical order.

At the moment I can specify the main haproxy.cfg file for the data plane API to use, but then it doesn't know about the configuration under conf.d/. It would be nice to be able to specify configuration file locations in much the same way as the haproxy command can load multiple config files.

Add ipv4 stats socket support

uname -a

Linux b02.example.com 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

haproxy -vv

HA-Proxy version 2.0.3 2019/07/23 - https://haproxy.org/
Build options :
  TARGET  = linux-glibc
  CPU     = generic
  CC      = gcc
  CFLAGS  = -O2 -g -fno-strict-aliasing -DTCP_USER_TIMEOUT=18
  OPTIONS = USE_PCRE=1 USE_PCRE_JIT=1 USE_REGPARM=1 USE_LINUX_TPROXY=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1

Feature list : +EPOLL -KQUEUE -MY_EPOLL -MY_SPLICE +NETFILTER +PCRE +PCRE_JIT -PCRE2 -PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED +REGPARM -STATIC_PCRE -STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H -VSYSCALL +GETADDRINFO +OPENSSL -LUA +FUTEX +ACCEPT4 -MY_ACCEPT4 +ZLIB -SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL +SYSTEMD -OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS

Default settings :
  bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_THREADS=64, default=8).
Built with OpenSSL version : OpenSSL 1.1.1c  28 May 2019
Running on OpenSSL version : OpenSSL 1.1.1c  28 May 2019
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with network namespace support.
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with zlib version : 1.2.7
Running on zlib version : 1.2.7
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with PCRE version : 8.32 2012-11-30
Running on PCRE version : 8.32 2012-11-30
PCRE library supports JIT : yes
Encrypted password support via crypt(3): yes

Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
              h2 : mode=HTX        side=FE|BE     mux=H2
              h2 : mode=HTTP       side=FE        mux=H2
       <default> : mode=HTX        side=FE|BE     mux=H1
       <default> : mode=TCP|HTTP   side=FE|BE     mux=PASS

Available services : none

Available filters :
        [SPOE] spoe
        [COMP] compression
        [CACHE] cache
        [TRACE] trace

dataplaneapi -v

HAProxy Data Plane API v1.1.0 c716ebf.dev

Build from: https://github.com/haproxytech/dataplaneapi.git
Build date: 2019-07-26T09:22:47

When running the dataplaneapi with the following configuration set in haproxy, dataplaneapi complains about the ipv4 socket existing and won't return data:

haproxy.cfg:

global
    ssl-mode-async
    log /dev/log   local0 debug
    log 127.0.0.1   local1 debug
    maxconn 4096
    user haproxy
    group haproxy
    daemon
    tune.ssl.default-dh-param 2048
    node lb02.example.com
    stats socket /run/haproxy.sock user haproxy group haproxy mode 660 level admin
    stats socket [email protected]:3333 level admin
    master-worker
    spread-checks 2
    mailers mta
    mailer smtp.example.com 192.168.3.26:25

if i GET
http://haproxy.example.com:5555/v1/services/haproxy/stats/native?type=server&parent=internet_443&name=web07

the response is:

{"code":500,"message":"dial unix [email protected]:3333: connect: no such file or directory"}

The CPU consumption of Dataplaneapi is on a high level as 150%

Hello everyone,
Im running the HAProxy(2.0.5) with dataplaneapi on Ubuntu and Mac . I see that dataplaneapi process consumes 150% of CPU while im doing nothing. I read some of the dataplaneapi code and found it is just a http server . Could anyone tell me why does this happen?Thanks a lot!

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1199 root 20 0 119144 36812 11036 S 147.8 0.5 16938:03 dataplaneapi

Question about releasing period for dataplaneapi

Hello,

we use datapane api dev version 1.2.4 at a client office for the
V2/specifications.

The client will feel more confortable to use this V2 version of the api
when it will be released officially.

Do you know when the dataplane api 1.2.4 or later will be released ?

Actually we use the dev version that we compiled.

Reload Command kill SIGUSR2 failed

We are running Haproxy and the Data plane API in the same Docker Container. After Updating the haproxy.cfg via the API, the reload command fails. It seems that the kill command can not be executed with the user who runs the data plane API, it only works as root.

$ kill -12 1
-sh: 1: kill: Operation not permitted

As per this Documentation it should work without root permissions. Is there a workaround?
https://www.haproxy.com/documentation/hapee/1-9r1/configuration/dataplaneapi/#configure-haproxy-to-start-the-api

Dataplaneapi returning previous version/outdated data after "raw" update

Dataplaneapi version:
`/ # /usr/local/bin/dataplaneapi --version
HAProxy Data Plane API v1.2.3 d6b862c

Build from: [email protected]:haproxytech/dataplaneapi.git
Build date: 2019-08-28T15:11:49`

After PUT /configuration/raw with new definitions, Dataplaneapi is not returning updated values on subsequent calls. Either way, GET /configuration/raw returns expected results, while GET /configuration/frontends (or backends/acls/binds) doesn't.

Old values (please notice _version mismatch):
/ # curl -X GET -H 'Cache-Control: no-cache' --user admin:admin -H "Content-Type: application/json" "http://localhost:5555/v1/services/haproxy/configuration/frontends"

{"_version":12,"data":[{"client_timeout":120000,"default_backend":"be_http-app-svc,"mode":"http","name":"fe_port443"},{"client_timeout":7200000,"default_backend":"backend-port443_2","mode":"http","name":"port443"},{"client_timeout":7200000,"default_backend":"backend-port80","mode":"http","name":"port80"}]}

GET raw snippet, returns updated and expected data:

/ # curl -X GET -H 'Cache-Control: no-cache' --user admin:admin -H "Content-Type: application/json" "http://localhost:5555/v1/services/haproxy/configuration/raw"
{"_version":13,"data":"\nglobal \n daemon\n master-worker\n maxconn 4000\n pidfile /var/run/haproxy.pid\n stats socket /var/lib/stats\n tune.ssl.default-dh-param 1024\n log 127.0.0.1 local2\n chroot /var/lib\n user nobody\n group nobody\n # turn on stats unix socket\n\ndefaults \n mode tcp\n maxconn 3000\n log global\n option httplog\n option redispatch\n option dontlognull\n ... ...

1- Doesn't work, even after kill SIGUSR2/HUP on haproxy.

Steps to reproduce:
1- PUT /config/raw - a plain text config with some change (I have changed fe timeout). I used version query instead transaction_id

2- GET /config/raw - changes are there, as expected. haproxy.cfg is also updated

3- GET /config/frontends - returns old data (please check "_version")

False successful concurrent requests

HAProxy: 2.0.5
dataplaneapi: v1.2.2
OS: Ubuntu 18.04

I'm trying to automate registering and unregistering backend servers (EC2 instances) in HAProxy using the API. It works well until I'm starting or stopping multiple backend servers at the same time. First I noticed that when I try to get the latest configuration version with GET request to /v1/services/haproxy/configuration/servers?backend=$BACKEND_NAME, it doesn't always return a proper response, probably because of HAProxy reload when another server gets registered or unregistered, so I'm retrying it a few times. After I get the configuration version, I'm making a request to either add or delete the server from HAProxy configuration. That's where things get weird: according to the documentation, request should fail if the provided configuration version is different from the latest one, and I expect that when I make multiple concurrent requests, only one of them would succeed, but in fact I get success 20* responses from all requests with the same configuration version, while only one of them gets actually executed.

Example requests:

curl -s -o /dev/null -w '%{http_code}' -X DELETE \
  --user admin:password \
  http://haproxy.internal:5555/v1/services/haproxy/configuration/servers/instance-1?force_reload=true&version=134&backend=$BACKEND_NAME

curl -s -o /dev/null -w '%{http_code}' -X DELETE \
  --user admin:password \
  http://haproxy.internal:5555/v1/services/haproxy/configuration/servers/instance-2?force_reload=true&version=134&backend=$BACKEND_NAME

Given instance-1 and instance-2 are registered and the latest backend configuration version is 134, running those requests in two terminals at the same time results in 204 in each terminal, but only instance-1 or instance-2 is actually removed from the configuration. Removing force_reload=true from the requests doesn't change this, both requests in this case return 202 but only one of the servers gets removed.

I might be doing something wrong, e. g. I didn't find any documented way of getting the latest configuration version, so I'm just parsing /v1/services/haproxy/configuration/servers?backend=$BACKEND_NAME response to get one. So please correct me if I am.

Here's my script that works pretty much every time, but is huge and full of hacks:

#!/bin/bash

# Usage:
# script.sh register $BACKEND_NAME $PORT
# script.sh unregister $BACKEND_NAME

set -ex

haproxy_url=http://haproxy.internal:5555
haproxy_username=admin
haproxy_password=password
cluster_size=3

ACTION="$1"
BACKEND_NAME="$2"
BACKEND_PORT="$3"
VER_RETRIES=${cluster_size}
RETRIES=${cluster_size}
RANDOM=$$
SLEEP_MIN=1
SLEEP_MAX=${cluster_size}

PRIVATE_IP=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
REGION=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/[a-z]$//')
INSTANCE_NAME=$(aws ec2 describe-tags --region="$REGION" --filters "Name=resource-id,Values=$INSTANCE_ID" Name=key,Values=Name --query Tags[].Value --output text)

haproxyConfVersion() {
  VER_RES=$(curl -s -w '\n%{http_code}' -X GET --user "${haproxy_username}:${haproxy_password}" "${haproxy_url}/v1/services/haproxy/configuration/servers?backend=$BACKEND_NAME")
  VER_RES_CODE=$(echo "$VER_RES" | tail -1)
  if [ "$VER_RES_CODE" != "200" ]; then
    if [ $VER_RETRIES -gt 0 ]; then
      VER_RETRIES=$((VER_RETRIES - 1))
      echo >&2 'WARNING: Failed to fetch HAProxy configuration version. Retrying.'
      sleep $((RANDOM % SLEEP_MAX + SLEEP_MIN))
      haproxyConfVersion
      return $?
    fi
    echo >&2 'ERROR: Failed to fetch HAProxy configuration version.'
    return 2
  fi

  echo "$VER_RES" | head -1 | jq -r '._version'
  return 0
}

haproxyServerExists() {
  RESPONSE_CODE=$(
    curl -s -o /dev/null -w %{http_code} -X GET \
      --user "${haproxy_username}:${haproxy_password}" \
      "${haproxy_url}/v1/services/haproxy/configuration/servers/$INSTANCE_NAME?backend=$BACKEND_NAME"
  )
  if [ "$RESPONSE_CODE" = "200" ]; then
    echo 'true'
  else
    echo 'false'
  fi
}

haproxyRegister() {
  HAPROXY_BE_VERSION=$(haproxyConfVersion)
  if [ "$HAPROXY_BE_VERSION" = "null" ] || [ "$HAPROXY_BE_VERSION" = "" ]; then
    echo >&2 'ERROR: HAProxy configuration version is invalid.'
    exit 1
  fi
  RESPONSE_CODE=$(
    curl -s -o /dev/null -w %{http_code} -X POST \
      --user "${haproxy_username}:${haproxy_password}" \
      -H "Content-Type: application/json" \
      -d "{\"address\":\"$PRIVATE_IP\",\"check\":\"enabled\",\"cookie\":\"A\",\"name\":\"$INSTANCE_NAME\",\"port\":$BACKEND_PORT}" \
      "${haproxy_url}/v1/services/haproxy/configuration/servers?force_reload=true&version=$HAPROXY_BE_VERSION&backend=$BACKEND_NAME"
  )

  if [ "$RESPONSE_CODE" != "201" ] || [ "$(haproxyServerExists)" = "false" ]; then
    if [ $RETRIES -gt 0 ]; then
      RETRIES=$((RETRIES - 1))
      echo >&2 'WARNING: Failed to register the instance in HAProxy. Retrying.'
      sleep $((RANDOM % SLEEP_MAX + SLEEP_MIN))
      haproxyRegister
      return $?
    fi
    echo >&2 'ERROR: Failed to register the instance in HAProxy.'
    return 2
  fi

  return 0
}

haproxyUnregister() {
  HAPROXY_BE_VERSION=$(haproxyConfVersion)
  if [ "$HAPROXY_BE_VERSION" = "null" ] || [ "$HAPROXY_BE_VERSION" = "" ]; then
    echo >&2 'ERROR: HAProxy configuration version is invalid.'
    exit 1
  fi
  RESPONSE_CODE=$(
    curl -s -o /dev/null -w %{http_code} -X DELETE \
      --user "${haproxy_username}:${haproxy_password}" \
      "${haproxy_url}/v1/services/haproxy/configuration/servers/$INSTANCE_NAME?force_reload=true&version=$HAPROXY_BE_VERSION&backend=$BACKEND_NAME"
  )
  if [ "$RESPONSE_CODE" != "204" ] || [ "$(haproxyServerExists)" = "true" ]; then
    if [ $RETRIES -gt 0 ]; then
      RETRIES=$((RETRIES - 1))
      echo >&2 'WARNING: Failed to unregister the instance in HAProxy. Retrying.'
      sleep $((RANDOM % SLEEP_MAX + SLEEP_MIN))
      haproxyUnregister
      return $?
    fi
    echo >&2 'ERROR: Failed to unregister the instance in HAProxy.'
    return 2
  fi

  return 0
}

if [ "$ACTION" = "unregister" ]; then
  haproxyUnregister && echo "Instance $INSTANCE_NAME unregistered from $BACKEND_NAME." || (
    echo "ERROR: Failed to unregister instance $INSTANCE_NAME from $BACKEND_NAME."
    exit 1
  )
else
  haproxyRegister && echo "Instance $INSTANCE_NAME registered in $BACKEND_NAME." || (
    echo "ERROR: Failed to register instance $INSTANCE_NAME in $BACKEND_NAME."
    exit 1
  )
fi

Backend balance algorithms

Hello,

Currently, according to the swagger schema and the x-dependency property of Backend.balance.arguments, only when uri and uri_param balance algorithms are chosen, it is possible to send additional arguments in the arguments array. For all other algorithms it's not possible to send additional arguments.

However, according to the configuration documentation the following balance algorithms should also probably be included, and accept additional arguments:

  • random - which accepts an integer, a number of draws for the consistent hashing function (the number of times a random server is selected before choosing the last loaded of those selected) and should render like this:

    balance random(3)
  • hdr - this is not currently part of the Swagger schema, this algorithm accepts a header name as string parameter, and additional use_domain_only parameter and should get rendered as:

    balance hdr(HeaderName)
    balance hdr(HeaderName) use_domain_only

    it would probably be best if the first argument in the array is rendered inside the parenthesis;

  • rdp-cooke - this algorithm is also not currently part of the Swagger schema, it accepts a name of the cookie for RDP protocol and defaults to mstshash if not present, rendered as:

    balance rdp-cookie(somecookie)

    again, I'd propose that the first argument in the array is rendered inside the parenthesis.

I suppose these are used infrequently but it'd still be great to have all the possibilities of config file covered by the API.

error detected in frontend while parsing 'http-request redirect' rule

HAProxy Data Plane API v1.2.4 0634304.dev
HA-Proxy version 2.1.0 2019/11/25

we are using a bunch of ACLs on our haproxy services, thus with dataplane api trying to enable server maintenance, i get errors listed below. It might be a similar bug that had experience before.

Haproxy config valdiation: Configuration file is valid

Several examples:

config line:
http-request redirect code 301 location https://site.d1.randomsite.com/healthcheck.html if { path_beg -m beg -i /health-check.html AND hdr_beg(host) -i www }

Error
{ "code": 400, "message": "14: ERR transactionId=2b53e98a-b126-4e7f-a30f-83c62da5aeca \nline=283 msg=\"error detected in frontend 'incomming' while parsing 'http-request redirect' rule expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '{').\"" }

config lines
acl root_path_cond path -i /
acl site_domain_cond hdr(host) -i www.d1.randomsite.com
http-request redirect code 301 location http://site.d1.randomsite.com if site_domain_cond root_path_cond
error:
{ "code": 400, "message": "14: ERR transactionId=ae7236be-366a-4c42-a4b4-298ca7c0b9a0 \nline=283 msg=\"error detected in frontend 'incomming' while parsing 'http-request redirect' rule expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was 'site_domain_cond').\"" }

dataplaneapi can't read/access haproxy-master.sock

I'm trying to call this endpoint but the response from the API is this
http://192.168.144.225:5555/v2/services/haproxy/stats/native


[
  {
    "error": "dial unix unix@/run/haproxy-master.sock: connect: no such file or directory",
    "runtimeAPI": "unix@/run/haproxy-master.sock@1",
    "stats": null
  }
]
evidently the socket file exist in the filesystem
root@LB01:~# ls -al /run/haproxy-master.sock 
srwxr-xr-x 1 root root 0 Nov  9 16:24 /run/haproxy-master.sock
root@LB01:~# 

haproxy snippet config
program api
    command dataplaneapi --host 192.168.144.225 --port 5555 --haproxy-bin /usr/sbin/haproxy --config-file /etc/haproxy/haproxy.cfg --reload-cmd "systemctl reload haproxy" --reload-delay 5 --userlist controller

userlist controller
    user superadmin password $5$IjsO5NsBcuMA1$qOv1sUuaEVGqbqTjSxmVbc//CxRKCfiyPr/Z.2wwu4/

Add options 'send-proxy' and 'send-proxy-v2' for a server at a backend

In order to properly pass through TCP traffic through a couple of load balancers it is necessary for me to be able to add both options send-proxy and send-proxy-v2 to a server line in a backend section.

F.E.

backend smtp
  server smtp smtp:10025 check inter 2500 send-proxy

backend imap
  server imap imap:10143 check inter 2500 send-proxy-v2

add support for external-check

I'm using following haproxy.cfg with haproxy 2.0.
I want to manage the config with dataplane api. However it doesn't support external-check and on-marked-down yet.

global
    ......
    external-check

listen citus-coordinator-master
    bind *:5440
    mode tcp
    balance first
    option external-check
    external-check path "/usr/bin:/bin"
    external-check command /usr/local/bin/pg_is_master.sh
    server co0 10.126.144.141:10000 check inter 5000 on-marked-down shutdown-sessions
    server co1 10.126.144.142:10001 check inter 5000 on-marked-down shutdown-sessions

runtime error: slice bounds out of range

Whenever I run dataplaneapi, I get the following error message:
time="2019-07-12T16:22:57Z" level=fatal msg="Error starting Data Plane API: runtime error: slice bounds out of range"

I get this both when building against source or downloading the pre-built binary. The error occurs on both Ubuntu 18.04 and CentOS 7.6. I'm running go version go1.12.7 linux/amd64 on both.

Default section written before global causing log problems

First of all, apologies if the problem is obvious because this is my first experience with the dataplaneapi.

So I want to register a new server to the backend depending upon the current rate of requests. I am able to register a new server in the backend and even through it is showing in the /etc/haproxy/haproxy.cfg, still the server is not handling any requests from the frontend. I have verified that the port is accessible and the server is indeed part of the backends.

import json
import time
import requests
from requests.auth import HTTPBasicAuth

def addServersToBackEnd(backEnd):
    uri = "http://localhost:5555/v1/services/haproxy/configuration/servers"
    version = getVersion(backEnd)
    transactionId = getTransactionId(version)
    params = {
        'backend': backEnd,
        'transaction_id': transactionId
    }
    data = {"name": "Server1", "address": "1.1.1.1", "port": 1234, "check": "enabled", "weight": 100}
    res = requests.post(uri, auth=HTTPBasicAuth('dataplaneapi','redacted'), params = params, json = data)
    commitTransaction = 'http://localhost:5555/v1/services/haproxy/transactions/' + transactionId
    res = requests.put(commitTransaction, auth=HTTPBasicAuth('dataplaneapi', 'redacted'))
    
def getTransactionId(version):
    uri = "http://localhost:5555/v1/services/haproxy/transactions"
    params = {
        'version': version
    }
    res = requests.post(uri, auth=HTTPBasicAuth('dataplaneapi', 'redacted'), params = params)
    data = res.json()
    transactionId = data['id']
    return transactionId

def getVersion(backEnd):
    uri = "http://localhost:5555/v1/services/haproxy/configuration/servers"
    params = {
        'backend': backEnd
    }
    res = requests.get(uri, auth=HTTPBasicAuth('dataplaneapi', 'redacted'), params = params)
    if res.status_code == 200:
        data = res.json()
        version = data['_version']
        return version

uri = 'http://localhost:5555/v1/services/haproxy/stats/native'
params = {
    'type': 'backend',
    'name': 'MyBackEnd'
}
serverAdded = False
while True:
    try:
        res = requests.get(uri, auth=HTTPBasicAuth('dataplaneapi', 'redacted'), params = params)
        if res.status_code == 200:
            data = res.json()
            rate = data[0]['stats'][0]['stats']['rate']
            print("Backend: {0}, Connections:{1}".format(str(params['name']),str(rate)))
            if rate > 100 and not serverAdded:
                 addServersToBackEnd(params['name'])
                 serverAdded = True
            else:
                print("Requests under the limit")
        else:
            print("An error occurred while querying the API. Error code is {0}".format(str(res)))
    except requests.exceptions.RequestException as e:
        print e
    time.sleep(1)

After this, the server 1.1.1.1 is successfully added to the backend 'MyBackEnd'. However, the incoming requests are still only served by the servers already configured in the backend before the changes committed by the dataplaneapi.

Thank you very much for reading. Any help would be greatly appreciated.

HTTP response rule "del-header" is not returned

Hi,

assuming I have the following frontend configuration:

frontend http
  bind *:80
  mode http
  http-response del-header X-Powered-By
  default_backend default

the http_response_rules endpoint with parent_name=http&parent_type=frontend returns emtpy rule list.

Same applies to backends.

Albeit other response rules (add-header, set-header, replace-header) are returned.

error 500 when adding backend with default_server other than "fall".

POST /v1/services/haproxy/configuration/backends?transaction_id=53c262e7-e491-4272-b93d-eaad98f5f4c0 HTTP/1.1
User-Agent: HTTPie/1.0.3
Accept-Encoding: gzip, deflate
Accept: application/json, /
Connection: keep-alive
Content-Type: application/json
Content-Length: 125
Authorization: Basic xxx
Host: docker-haproxy-certbot_server_1:5555

{"balance": {"algorithm": "random"}, "default_server": {"inter": 5000}, "name": "my_backend"}

HTTP/1.1 500 Internal Server Error
Vary: Origin
Date: Fri, 22 Nov 2019 10:54:29 GMT
Content-Length: 137
Content-Type: text/plain; charset=utf-8

{"code":500,"message":"runtime error: invalid memory address or nil pointer dereference: /usr/local/go/src/runtime/panic.go:81 panicmem"}

I'm fairly sure this happens because of buggy code in client-native configuration.go, but alas I thought it would be nice to track it here in case others experience the same issue.

Issue seems to stem from a typo, where the wrong parameter is used:
https://github.com/haproxytech/client-native/blob/v1.2.6/configuration/configuration.go#L789

if ds.Inter != nil {
	param := &params.ServerOptionValue{
		Name:  "inter",
		Value: strconv.FormatInt(*ds.Fall, 10), // <-- I think this should be *ds.Inter, but I don't know go.
	}
	ps = append(ps, param)
}

time="2019-11-22T10:54:29Z" level=info msg="started handling request" method=POST remote="172.25.0.3:43872" request="/v1/services/haproxy/configuration/backends?transaction_id=53c262e7-e491-4272-b93d-eaad98f5f4c0"
time="2019-11-22T10:54:29Z" level=error msg="Panic runtime error: invalid memory address or nil pointer dereference" stack_trace="\n/usr/local/go/src/runtime/panic.go:81 panicmem\n/home/mjuraga/projects/go/pkg/mod/github.com/haproxytech/[email protected]/configuration/configuration.go:783 (*Client).setFieldValue\n/home/mjuraga/projects/go/pkg/mod/github.com/haproxytech/[email protected]/configuration/configuration.go:635 (*Client).createEditSection\n/home/mjuraga/projects/go/pkg/mod/github.com/haproxytech/[email protected]/configuration/configuration.go:1181 (*Client).createSection\n/home/mjuraga/projects/go/pkg/mod/github.com/haproxytech/[email protected]/configuration/backend.go:100 (*Client).CreateBackend\n/home/mjuraga/projects/haproxytech/dataplaneapi/handlers/backend.go:76 (*CreateBackendHandlerImpl).Handle\n/home/mjuraga/projects/haproxytech/dataplaneapi/operations/backend/create_backend.go:84 (*CreateBackend).ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/operation.go:28 NewOperationExecutor.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/router.go:76 NewRouter.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/redoc.go:72 Redoc.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/go-openapi/[email protected]/middleware/spec.go:46 Spec.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/haproxytech/dataplaneapi/adapters/adapters.go:151 RecoverMiddleware.func1.1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/go/pkg/mod/github.com/rs/[email protected]/cors.go:207 (*Cors).Handler.func1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/home/mjuraga/projects/haproxytech/dataplaneapi/adapters/adapters.go:165 LoggingMiddleware.func1.1\n/usr/local/go/src/net/http/server.go:1995 HandlerFunc.ServeHTTP\n/usr/local/go/src/net/http/server.go:2774 serverHandler.ServeHTTP\n/usr/local/go/src/net/http/server.go:1878 (*conn).serve\n/usr/local/go/src/runtime/asm_amd64.s:1337 goexit"

'crt' missing certificate location

Haproxy v2.0.5

`HA-Proxy version 2.0.5 2019/08/16 - https://haproxy.org/
Build options :
TARGET = linux-glibc
CPU = generic
CC = gcc
CFLAGS = -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-old-style-declaration -Wno-ignored-qualifiers -Wno-clobbered -Wno-missing-field-initializers -Wtype-limits
OPTIONS = USE_PCRE=1 USE_PCRE_JIT=1 USE_THREAD=1 USE_REGPARM=1 USE_LINUX_TPROXY=1 USE_OPENSSL=1 USE_ZLIB=1 USE_TFO=1 USE_SYSTEMD=1

Feature list : +EPOLL -KQUEUE -MY_EPOLL -MY_SPLICE +NETFILTER +PCRE +PCRE_JIT -PCRE2 -PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED +REGPARM -STATIC_PCRE -STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H -VSYSCALL +GETADDRINFO +OPENSSL -LUA +FUTEX +ACCEPT4 -MY_ACCEPT4 +ZLIB -SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL +SYSTEMD -OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS

Default settings :
bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_THREADS=64, default=2).
Built with OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
Running on OpenSSL version : OpenSSL 1.0.2k-fips 26 Jan 2017
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : SSLv3 TLSv1.0 TLSv1.1 TLSv1.2
Built with network namespace support.
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with zlib version : 1.2.7
Running on zlib version : 1.2.7
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with PCRE version : 8.32 2012-11-30
Running on PCRE version : 8.32 2012-11-30
PCRE library supports JIT : yes
Encrypted password support via crypt(3): yes
Built with the Prometheus exporter as a service

Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as cannot be specified using 'proto' keyword)
h2 : mode=HTX side=FE|BE mux=H2
h2 : mode=HTTP side=FE mux=H2
: mode=HTX side=FE|BE mux=H1
: mode=TCP|HTTP side=FE|BE mux=PASS

Available services :
prometheus-exporter

Available filters :
[SPOE] spoe
[COMP] compression
[CACHE] cache
[TRACE] trace`

HAProxy Data Plane API v1.2.4 9804b65.dev

I have serveral frontend binds defined as in example and using multiple certificates
bind *:443 ssl no-sslv3 crt /etc/haproxy/certificates/

While executing simple payload, no matter what changes there would be
# maint.json { "address":"10.10.1.10", "check":"enabled", "maintenance":"enabled", "name":"srv01", "port":10138 }

I get to such error code
{ "code": 400, "message": "14: ERR transactionId=2ca2f57d-74a0-4c58-a957-570c51f1adf8 \nline=35 msg=\"'bind *:443' 'crt' missing certificate location\"\nline=1278 msg=\"'bind *:10104' 'crt' missing certificate location\"\nline=1409 msg=\"'bind *:20087' 'crt' missing certificate location\"\nline=2052 msg=\"'bind *:11458' 'crt' missing certificate location\"\nline=2247 msg=\"'bind *:4440' 'crt' missing certificate location\"\nline=2298 msg=\"'bind *:11459' 'crt' missing certificate location\"" }

Same error appears while defining certificates one by one
bind *:443 ssl no-sslv3 crt /etc/haproxy/certificates/test_com.pem crt /etc/haproxy/certificates/test_zone.pem crt /etc/haproxy/certificates/app_test_zone.pem

Both haproxy and dataplaneapi serivces run under root to be sure it is not a permissions issue.

Dataplane API and docker (Error reading userlist dataplane-api userlist in conf: section missing")

Hello everyone,

iam running the haproxy container (version 2.0.6) and trying to set up the data plane api with it.
I have edited the docker-entry to download the latest data plane version and start it via the
haproxy program section inside the config.

Unfortunately I have a problem with accessing the userlist and haproxy reports the following warning when starting.

time="2019-09-23T12:42:48Z" level=warning msg="Runtime API not configured, not using it"

When I use the same config on a normal linux host with haproxy installed everything is working. I think it could be an issue with the socket inside the docker container and the resulting warning message i have received.

Are there any "best practices" how to set up the new api with the docker version of haproxy?

global
    log stdout format raw local0 info
    stats socket [email protected]:9999 level admin
    stats socket /var/run/haproxy.sock mode 666 level admin
    stats timeout 30s
    master-worker 
    daemon


defaults
    log global
    option http-server-close
    option httplog
    mode http
    timeout http-request 5s
    timeout connect 5s
    timeout server 10s
    timeout client 30s



listen stats
    bind 0.0.0.0:1454
    mode http
    option http-use-htx
    http-request use-service prometheus-exporter if { path /metrics }
    stats enable
    stats hide-version
    stats uri /stats
    http-request set-log-level silent


userlist dataplane-api
    user admin password ****

program api
    command dataplaneapi --host 0.0.0.0 --port 5555 --haproxy-bin /usr/sbin/haproxy --config-file /etc/haproxy/haproxy.cfg --reload-cmd "service haproxy reload" --reload-delay 5 --userlist dataplane-api
    no option start-on-reload



frontend proxy_in
    bind [email protected]:80
    default_backend proxy_out

backend proxy_out
    server backend_01 0.0.0.0:443 ssl verify none check weight 1 maxconn 3000

reqirep / rspirep not supported in dataplaneapi

I went thru API documentation, but didn't find anything.

Looking for a way to add below rewrite statements to a Backend, thru API:

 reqirep  ^(GET|POST|PUT|DELETE|HEAD)\ /(.*)     \1\ /\2
 rspirep ^Location:\ (http|https)://mybackend.domain.com\/(.*)   Location:\ \1://myfronted.domain.com.br/\2

Am I missing something?

Posibility to have backend drain via dataplane API

Hello, HaProxy has backend server drain functionality, it would be great to have drain funkcionality via REST API. Is it possible to include it or get some guidance how to contribute to add it.

Thanks

Cannot get TLS working

Hi,

I'm trying to get the dataplane API working with TLS to use HAProxy+dataplane API as the default load balancer for the OSS Kubernetes Cluster API provider for vSphere. I've got a WiP branch at https://github.com/akutz/cluster-api-provider-vsphere/tree/feature/haproxy/hack/tools/haproxy, but the tests I'm doing with TLS show the dataplane API server is never actually serving on the specified TLS port:

$ dataplaneapi \
  --host=0.0.0.0 \
  --port=5555 \
  --haproxy-bin=/usr/sbin/haproxy \
  --config-file=/etc/haproxy/haproxy.cfg \
  --reload-cmd="killall -SIGUSR2 haproxy" \
  --reload-delay=5 \
  --tls-host=0.0.0.0 \
  --tls-port=5556 \
  --tls-certificate=/etc/haproxy/server.crt \
  --tls-key=/etc/haproxy/server.key \
  --tls-ca=/etc/haproxy/ca.crt \
  --userlist=controller \
  --log-level=debug
time="2019-12-23T19:27:39Z" level=info msg="HAProxy Data Plane API v1.2.4 a5a8984"
time="2019-12-23T19:27:39Z" level=info msg="Build from: [email protected]:haproxytech/dataplaneapi.git"
time="2019-12-23T19:27:39Z" level=info msg="Build date: 2019-10-09T15:38:21"
time="2019-12-23T19:27:39Z" level=info msg="Serving data plane at http://[::]:5555"

I try with curl over the normal port, 5555, and all is well:

$ curl -u root:admin http://localhost:5555/v1/info
{"api":{"build_date":"2019-10-09T15:38:21.000Z","version":"v1.2.4 a5a8984"},"system":{}}

But when I try using TLS over port 5556:

$ curl -k https://localhost:5556
curl: (7) Failed to connect to localhost port 5556: Connection refused

I suspect the TLS server isn't even starting since I don't see a bind entry in the above debug log. What's more, if I provide invalid paths for the server and CA cert/key files, I don't even receive an error on startup:

$ dataplaneapi \
  --host=0.0.0.0 \
  --port=5555 \
  --haproxy-bin=/usr/sbin/haproxy \
  --config-file=/etc/haproxy/haproxy.cfg \
  --reload-cmd="killall -SIGUSR2 haproxy" \
  --reload-delay=5 \
  --tls-host=0.0.0.0 \
  --tls-port=5556 \
  --tls-certificate=/etc/haproxy/server.crt.invalid \
  --tls-key=/etc/haproxy/server.key.invalid \
  --tls-ca=/etc/haproxy/ca.crt.invalid \
  --userlist=controller \
  --log-level=debugtime="2019-12-23T19:31:52Z" level=info msg="HAProxy Data Plane API v1.2.4 a5a8984"
time="2019-12-23T19:31:52Z" level=info msg="Build from: [email protected]:haproxytech/dataplaneapi.git"
time="2019-12-23T19:31:52Z" level=info msg="Build date: 2019-10-09T15:38:21"
time="2019-12-23T19:31:52Z" level=info msg="Serving data plane at http://[::]:5555"

I'd appreciate any help you are able to provide. Thank you!

Version info

dataplane API

dataplaneapi --version
HAProxy Data Plane API v1.2.4 a5a8984

Build from: [email protected]:haproxytech/dataplaneapi.git
Build date: 2019-10-09T15:38:21

haproxy

haproxy -h 2>/dev/null | head -n2
HA-Proxy version 2.0.3 2019/07/23 - https://haproxy.org/

blocking kubernetes-sigs/cluster-api-provider-vsphere#705

Checksum mismatch with client-native

Hello,

when I try to build the dataplaneapi, I get a checksum mismatch:

# make 
go get -v
verifying github.com/haproxytech/[email protected]: checksum mismatch
	downloaded: h1:uY9KMY5fu/7vcpi2lL3jQ6MgvJsU8e7YgL6AvGeDOLs=
	go.sum:     h1:z07dOpU9Q+1gDc5n8NTjkYu3GFOFWoe3Hf/HSN30AXA=
Makefile:14: recipe for target 'update' failed
make: *** [update] Error 1

I am using golang 1.12.6:

# go version
go version go1.12.6 linux/amd64

Am I missing something or is it possible to solve this?

Kind regards,
Simon

Error message for missing haproxy binary is confusing

Hi,

I had a typo in my systemd unit for the data plane service, pointing the --haproxy-bin option to /usr/bin/haproxy instead of /usr/sbin/haproxy. This resulted in useless error messages from any endpoints that wanted to use the binary, e.g.:

% curl -X POST --user dataplaneapi:password \                                                       
  -H "Content-Type: application/json" \
  -d '{"name": "test_frontend", "default_backend": "be_web", "mode": "http", "maxconn": 2000}' \
  "http://localhost:5555/v1/services/haproxy/configuration/frontends?version=1"
{"code":400,"message":"14: ERR transactionId=5636c5df-8f09-4b61-b73f-02a044f4d5e7 "}

Enabling debug-level logging in the dataplane service didn't reveal the cause of this error either:

# /usr/bin/dataplaneapi --host 0.0.0.0 --port 5555 --haproxy-bin /usr/bin/haproxy --config-file /etc/haproxy/haproxy.cfg --reload-cmd "systemctl reload haproxy" --reload-delay 5 --userlist dataplane-api --log-to=stdout --log-level=debug
time="2019-08-26T13:38:54Z" level=info msg="HAProxy Data Plane API v1.2.2 d5bbf85"
time="2019-08-26T13:38:54Z" level=info msg="Build from: [email protected]:haproxytech/dataplaneapi.git"
time="2019-08-26T13:38:54Z" level=info msg="Build date: 2019-08-21T18:06:31"
time="2019-08-26T13:38:54Z" level=info msg="Serving data plane at http://[::]:5555"
time="2019-08-26T13:38:58Z" level=info msg="started handling request" method=POST remote="10.0.2.2:49980" request="/v1/services/haproxy/configuration/frontends?version=1"
time="2019-08-26T13:38:58Z" level=info msg="completed handling request" length=85B status=400 took=1.344026ms

The lack of error message or log messages pointing to the cause lead to this issue taking much longer to diagnose than it should have. Increased logging and validation of command line arguments would help in the future.

Edit: For reference, this was with Data Plane v1.2.2 and HAProxy 2.0.5 on CentOS 7.

Support mutual cert verification as only form of auth

While the dataplane API server supports mutual TLS verification as a form of authentication, it's still necessary to supply some form of username/password. It would be nice to rely solely on the peer verification as the only form of authentication.

/v1/services/haproxy/stats/native?type=server does not return all servers

Querying the following URL:
/v1/services/haproxy/stats/native?type=server

I notice that a lot of servers we have and associated backends do not appear in the output.

Is there an upper limit to the number of entries returned? How can I retrieve every server?

Currently using dataplane v1.2.4

Some counts:

$ grep "  server" haproxy-http.cfg | wc -l
43
$ grep '^backend' haproxy-http.cfg | wc -l
37
$ curl http://username:[email protected]:55550/v1/services/haproxy/stats/native?type=server | grep -o server | wc -l
27

Dynamic SSL Certificate Updates

First of all, thanks for this new great 2.0 release.

Regarding the "Dynamic SSL Certificate Updates" 2.1 coming feature, I was wondering If that feature means we'll be able to read and write through the API the certs haproxy uses on the bind option.

I am using kubernetes and in the meantime I am planning on changing the certs though the kubernetes API and reloading haproxy with the haproxy API.

Thanks very much for your help and good work.

Dataplaneapi no longer builds from source

This worked fine up to 1.1.1 but fails from 1.2.0 and current master


[EnvInject] - Loading node environment variables.
Building remotely on Build node in workspace /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI
[Compile_HAProxy_DataPlaneAPI] $ /bin/sh -xe /tmp/jenkins5158224125040382183.sh
+ rm -rf go go1.12.7.src.tar.gz go-linux-amd64-bootstrap go-linux-amd64-bootstrap.tbz src
++ pwd
+ JENKINS_DIR=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI
+ cd /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI
+ wget https://storage.googleapis.com/golang/go1.12.7.src.tar.gz
--2019-08-12 10:54:13--  https://storage.googleapis.com/golang/go1.12.7.src.tar.gz
Resolving storage.googleapis.com (storage.googleapis.com)... 172.217.169.48, 2a00:1450:4009:80d::2010
Connecting to storage.googleapis.com (storage.googleapis.com)|172.217.169.48|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 21976647 (21M) [application/octet-stream]
Saving to: ‘go1.12.7.src.tar.gz’

2019-08-12 10:54:14 (41.0 MB/s) - ‘go1.12.7.src.tar.gz’ saved [21976647/21976647]

+ tar xf go1.12.7.src.tar.gz
+ cd go/src
+ GOROOT_BOOTSTRAP=/usr/lib/golang
+ GOOS=linux
+ GOARCH=amd64
+ ./bootstrap.bash
#### Copying to ../../go-linux-amd64-bootstrap

#### Cleaning ../../go-linux-amd64-bootstrap

#### Building ../../go-linux-amd64-bootstrap

Building Go cmd/dist using /usr/lib/golang.
Building Go toolchain1 using /usr/lib/golang.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
----
Bootstrap toolchain for linux/amd64 installed in /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go-linux-amd64-bootstrap.
Building tbz.
-rw-r--r--. 1 wasadm was 116096607 Aug 12 10:56 /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go-linux-amd64-bootstrap.tbz
+ export GOROOT=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go
+ GOROOT=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go
+ export PATH=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/bin:/usr/local/bin:/usr/bin
+ PATH=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/bin:/usr/local/bin:/usr/bin
+ GOROOT_BOOTSTRAP=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go-linux-amd64-bootstrap
+ GOOS=linux
+ GOARCH=amd64
+ ./make.bash
Building Go cmd/dist using /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go-linux-amd64-bootstrap.
Building Go toolchain1 using /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go-linux-amd64-bootstrap.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go
Installed commands in /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go/bin
+ cd /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI
+ mkdir -p /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/src/github.com/haproxytech/
+ cd /apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/src/github.com/haproxytech/
+ /apps/was/git/bin/git clone https://github.com/haproxytech/dataplaneapi.git
Cloning into 'dataplaneapi'...
+ cd dataplaneapi
+ export GOPATH=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI
+ GOPATH=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI
+ export PATH=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go/bin:/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/bin:/usr/local/bin:/usr/bin
+ PATH=/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/go/bin:/apps/was/jenkins/workspace/Compile_HAProxy_DataPlaneAPI/bin:/usr/local/bin:/usr/bin
+ make
go get -v
go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src;
	ignoring go.mod;
	see 'go help modules'
github.com/GehirnInc/crypt (download)
github.com/go-openapi/errors (download)
github.com/go-openapi/runtime (download)
github.com/go-openapi/strfmt (download)
github.com/asaskevich/govalidator (download)
github.com/mitchellh/mapstructure (download)
Fetching https://go.mongodb.org/mongo-driver/bson?go-get=1
Parsing meta tags from https://go.mongodb.org/mongo-driver/bson?go-get=1 (status code 200)
get "go.mongodb.org/mongo-driver/bson": found meta tag get.metaImport{Prefix:"go.mongodb.org/mongo-driver", VCS:"git", RepoRoot:"https://github.com/mongodb/mongo-go-driver.git"} at https://go.mongodb.org/mongo-driver/bson?go-get=1
get "go.mongodb.org/mongo-driver/bson": verifying non-authoritative meta tag
Fetching https://go.mongodb.org/mongo-driver?go-get=1
Parsing meta tags from https://go.mongodb.org/mongo-driver?go-get=1 (status code 200)
go.mongodb.org/mongo-driver (download)
Fetching https://go.mongodb.org/mongo-driver/bson/bsontype?go-get=1
Parsing meta tags from https://go.mongodb.org/mongo-driver/bson/bsontype?go-get=1 (status code 200)
get "go.mongodb.org/mongo-driver/bson/bsontype": found meta tag get.metaImport{Prefix:"go.mongodb.org/mongo-driver", VCS:"git", RepoRoot:"https://github.com/mongodb/mongo-go-driver.git"} at https://go.mongodb.org/mongo-driver/bson/bsontype?go-get=1
get "go.mongodb.org/mongo-driver/bson/bsontype": verifying non-authoritative meta tag
Fetching https://go.mongodb.org/mongo-driver/bson/primitive?go-get=1
Parsing meta tags from https://go.mongodb.org/mongo-driver/bson/primitive?go-get=1 (status code 200)
get "go.mongodb.org/mongo-driver/bson/primitive": found meta tag get.metaImport{Prefix:"go.mongodb.org/mongo-driver", VCS:"git", RepoRoot:"https://github.com/mongodb/mongo-go-driver.git"} at https://go.mongodb.org/mongo-driver/bson/primitive?go-get=1
get "go.mongodb.org/mongo-driver/bson/primitive": verifying non-authoritative meta tag
github.com/go-openapi/swag (download)
github.com/mailru/easyjson (download)
Fetching https://gopkg.in/yaml.v2?go-get=1
Parsing meta tags from https://gopkg.in/yaml.v2?go-get=1 (status code 200)
get "gopkg.in/yaml.v2": found meta tag get.metaImport{Prefix:"gopkg.in/yaml.v2", VCS:"git", RepoRoot:"https://gopkg.in/yaml.v2"} at https://gopkg.in/yaml.v2?go-get=1
gopkg.in/yaml.v2 (download)
github.com/docker/go-units (download)
github.com/go-openapi/analysis (download)
github.com/go-openapi/jsonpointer (download)
github.com/go-openapi/spec (download)
github.com/go-openapi/jsonreference (download)
github.com/PuerkitoBio/purell (download)
github.com/PuerkitoBio/urlesc (download)
Fetching https://golang.org/x/net/idna?go-get=1
Parsing meta tags from https://golang.org/x/net/idna?go-get=1 (status code 200)
get "golang.org/x/net/idna": found meta tag get.metaImport{Prefix:"golang.org/x/net", VCS:"git", RepoRoot:"https://go.googlesource.com/net"} at https://golang.org/x/net/idna?go-get=1
get "golang.org/x/net/idna": verifying non-authoritative meta tag
Fetching https://golang.org/x/net?go-get=1
Parsing meta tags from https://golang.org/x/net?go-get=1 (status code 200)
golang.org/x/net (download)
Fetching https://golang.org/x/text/secure/bidirule?go-get=1
Parsing meta tags from https://golang.org/x/text/secure/bidirule?go-get=1 (status code 200)
get "golang.org/x/text/secure/bidirule": found meta tag get.metaImport{Prefix:"golang.org/x/text", VCS:"git", RepoRoot:"https://go.googlesource.com/text"} at https://golang.org/x/text/secure/bidirule?go-get=1
get "golang.org/x/text/secure/bidirule": verifying non-authoritative meta tag
Fetching https://golang.org/x/text?go-get=1
Parsing meta tags from https://golang.org/x/text?go-get=1 (status code 200)
golang.org/x/text (download)
Fetching https://golang.org/x/text/unicode/bidi?go-get=1
Parsing meta tags from https://golang.org/x/text/unicode/bidi?go-get=1 (status code 200)
get "golang.org/x/text/unicode/bidi": found meta tag get.metaImport{Prefix:"golang.org/x/text", VCS:"git", RepoRoot:"https://go.googlesource.com/text"} at https://golang.org/x/text/unicode/bidi?go-get=1
get "golang.org/x/text/unicode/bidi": verifying non-authoritative meta tag
Fetching https://golang.org/x/text/unicode/norm?go-get=1
Parsing meta tags from https://golang.org/x/text/unicode/norm?go-get=1 (status code 200)
get "golang.org/x/text/unicode/norm": found meta tag get.metaImport{Prefix:"golang.org/x/text", VCS:"git", RepoRoot:"https://go.googlesource.com/text"} at https://golang.org/x/text/unicode/norm?go-get=1
get "golang.org/x/text/unicode/norm": verifying non-authoritative meta tag
Fetching https://golang.org/x/text/width?go-get=1
Parsing meta tags from https://golang.org/x/text/width?go-get=1 (status code 200)
get "golang.org/x/text/width": found meta tag get.metaImport{Prefix:"golang.org/x/text", VCS:"git", RepoRoot:"https://go.googlesource.com/text"} at https://golang.org/x/text/width?go-get=1
get "golang.org/x/text/width": verifying non-authoritative meta tag
github.com/go-openapi/loads (download)
github.com/go-openapi/validate (download)
github.com/haproxytech/client-native (download)
github.com/google/uuid (download)
github.com/haproxytech/config-parser (download)
github.com/haproxytech/models (download)
github.com/pkg/errors (download)
github.com/sirupsen/logrus (download)
Fetching https://golang.org/x/sys/unix?go-get=1
Parsing meta tags from https://golang.org/x/sys/unix?go-get=1 (status code 200)
get "golang.org/x/sys/unix": found meta tag get.metaImport{Prefix:"golang.org/x/sys", VCS:"git", RepoRoot:"https://go.googlesource.com/sys"} at https://golang.org/x/sys/unix?go-get=1
get "golang.org/x/sys/unix": verifying non-authoritative meta tag
Fetching https://golang.org/x/sys?go-get=1
Parsing meta tags from https://golang.org/x/sys?go-get=1 (status code 200)
golang.org/x/sys (download)
github.com/jessevdk/go-flags (download)
github.com/rs/cors (download)
Fetching https://golang.org/x/net/netutil?go-get=1
Parsing meta tags from https://golang.org/x/net/netutil?go-get=1 (status code 200)
get "golang.org/x/net/netutil": found meta tag get.metaImport{Prefix:"golang.org/x/net", VCS:"git", RepoRoot:"https://go.googlesource.com/net"} at https://golang.org/x/net/netutil?go-get=1
get "golang.org/x/net/netutil": verifying non-authoritative meta tag
github.com/haproxytech/client-native/configuration
# github.com/haproxytech/client-native/configuration
../client-native/configuration/acl.go:69:24: undefined: types.Acl
../client-native/configuration/acl.go:183:13: undefined: "github.com/haproxytech/config-parser/errors".FetchError
../client-native/configuration/acl.go:189:22: undefined: types.Acl
../client-native/configuration/acl.go:201:17: undefined: types.Acl
../client-native/configuration/acl.go:209:33: undefined: types.Acl
../client-native/configuration/acl.go:210:9: undefined: types.Acl
../client-native/configuration/backend_switching_rule.go:151:13: undefined: "github.com/haproxytech/config-parser/errors".FetchError
../client-native/configuration/bind.go:164:13: undefined: "github.com/haproxytech/config-parser/errors".FetchError
../client-native/configuration/configuration.go:303:14: d.Uri undefined (type *types.OptionHttpchk has no field or method Uri, but does have URI)
../client-native/configuration/configuration.go:642:5: unknown field 'Uri' in struct literal of type types.OptionHttpchk (but does have URI)
../client-native/configuration/configuration.go:642:5: too many errors
make: *** [update] Error 2
Build step 'Execute shell' marked build as failure
Finished: FAILURE

Dataplane not reading certain tcp-request lines

I have a tcp-request section setup to do sni based routing but the dataplaneapi request to return the tcp-request rules seems to be missing one of the rules

My front end is configured as

frontend test_frontend
  mode tcp
  bind *:8080

  acl clienthello req_ssl_hello_type 1
  tcp-request inspect-delay 2s
  tcp-request content capture req.ssl_sni len 30
  log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq sni_hdr:%[capture.req.hdr(0)]"

  tcp-request content accept if clienthello

when i query the dataplane it is not returning the tcp-request content capture line

curl --user admin:password "http://localhost:5555/v1/services/haproxy/configuration/tcp_request_rules?parent_type=frontend&parent_name=test_frontend"
{"_version":121,"data":[{"id":0,"timeout":0,"type":"inspect-delay"},{"action":"accept","cond":"if","cond_test":"clienthello","id":2,"type":"content"}]}

interestingly the id count skips from 0 to 2 so i'm assuming it is picking up the line when it scans the config file but doesn't report it.

Support multiple ssl_certificate on frontend bindings

We use multiple SSL certificates for subdomain wildcards.
However the api does not allow to create a line as the following:
bind :443 name https crt domain.pem crt sub.domain.pem crt sub2.domain.pem ssl

the pem's would be for *.domain.com, *.sub.domain.com and *.sub2.domain.com
If we create multiple bind lines, it seems like HAProxy doesn't use SNI correctly, and is servers the first certificate most of the time.

OpenAPI spec creates Golang sources incompatible with examples

The examples at https://www.haproxy.com/documentation/hapee/1-9r1/configuration/dataplaneapi/ are incompatible with the Golang client bindings generated from the OpenAPI spec. Aside from having to create a program to remove the duplicate Opt structs, I've also had to do yet some more post-processing to make the Backend model compatible with the aforementioned examples:

.PHONY: fix-backend-model
fix-backend-model: | $(GOLANGCI_LINT)
fix-backend-model: $(OUTPUT_DIR)/model_backend.go
fix-backend-model: ## Makes optional fields in the backend model into pointers
	sed -i.bak \
	  -e 's~Forwardfor[[:space:]]\{1,\}Forwardfor~Forwardfor *Forwardfor~' \
	  -e 's~HashType[[:space:]]\{1,\}BackendHashType~HashType *BackendHashType~' \
	  -e 's~StickTable[[:space:]]\{1,\}BackendStickTable~StickTable *BackendStickTable~' \
	  $<
	$(GOLANGCI_LINT) run -v --no-config --fast=false --fix --disable-all --enable goimports $<
	@rm -f $<.bak

If those fields aren't pointers, then you end up with obtuse errors (when using transactions) as a result of trying to create a new backend. While the values of Forwardfor.Enabled, HashType.Method, BackendStickTable.Type, and BackendStickTable.Size may all be tagged as omitempty, the server disagrees when empty values are submitted for the struct (and thus its fields).

I had to do the following to get a backend successfully created in Golang, and I'm not even sure if those values are the defaults for those fields.

	// Create a backend.
	backend, _, err := client.BackendApi.CreateBackend(ctx, hapi.Backend{
		Name: "lb-backend",
		Mode: "tcp",
		Balance: hapi.Balance{
			Algorithm: "roundrobin",
		},
		Forwardfor: hapi.Forwardfor{
			Enabled: "enabled",
		},
		HashType: hapi.BackendHashType{
			Method: "consistent",
		},
		Redispatch: hapi.Redispatch{
			Enabled: "disabled",
		},
		AdvCheck: "tcp-check",
		StickTable: hapi.BackendStickTable{
			Type: "ip2",
			Size: ptrInt32(100),
		},
	}, &hapi.CreateBackendOpts{
		TransactionId: transactionID,
	})
	if err != nil {
		t.Fatalf("failed to create backend: %v", err)
	}

Add option 'allow-0rtt' for a bind of a frontend

Hi,

I am stuck at adding a ssl bind line like the following to a frontend:

bind *:443 name http_443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1 allow-0rtt

I am not able to set the alpn and the allow-0rtt.

Am I doing something wrong or oversee something? May you give me a tip on how to achieve that?

Expose maps through the API

Hi,
We want to use dataplaneapi to find out which is the backend for a specific service name like myapp.domain.com . We have the association stored in a map file, so, would it be possible to retrieve it through the API? I don't see any endpoint I can get that information from?

Cheers.

Setting the configuration for resolvers and init-addr for a server in backend section

I try to add a server to a backend section in my haproxy.cfg via data plane api. I can't find anything in the documentation how to set the configuration for resolvers and init-addr. e.g.: resolvers docker init-addr libc,none
I was able to configure the name, address and check with the /services/haproxy/configuration/servers endpoint
This is how it should be configured:

backend backend1
server server1 server1:80 check resolvers docker init-addr libc,none

How can I set these configurations or is it not yet possible?

Add support for SRV records

Based on the documentation for backends and servers: CreateBackend there doesn't appear to be a way to configure a server-template for a HAProxy backend. Could this be added to the road map to support more graceful service discovery? The use-case surrounds using Consul SRV DNS to resolve services: Service Discovery with Runtime API. Since backends can't be created with the runtime API that leaves the dataplane API.

Access control per resource

This is a feature request.

It would be nice if we are able to restrict the permissions of users to be able to configure certain elements within haproxy via the API.

For instance, user 'deployment' could add servers to various backends (specified by backend name), but not be allowed to modify other backends or frontend configurations.

This allows for environments that have multiple resources to use specific username / password combinations to affect each projects haproxy configuration resource without allowing complete control over haproxy.

tcp-request nto reporting timeout value correctly

My front end is configured as

frontend test_frontend
  mode tcp
  bind *:8080

  acl clienthello req_ssl_hello_type 1
  tcp-request inspect-delay 2s
  tcp-request content capture req.ssl_sni len 30
  log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq sni_hdr:%[capture.req.hdr(0)]"

  tcp-request content accept if clienthello

when i query the dataplane it is returning the record however the timeout value is set to 0 rather than 2

curl --user admin:password "http://localhost:5555/v1/services/haproxy/configuration/tcp_request_rules/0?pare
nt_type=frontend&parent_name=test_frontend"
{"_version":121,"data":{"id":0,"timeout":0,"type":"inspect-delay"}}

Ability to validate config

It would be very useful if one can upload file to dataplane api without applying it. For example POST /v1/services/haproxy/configuration/raw&only_validating=true

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.