Git Product home page Git Product logo

haproxy-formula's Introduction

haproxy-formula

Travis CI Build Status Semantic Release

Install, configure and run haproxy.

See the full SaltStack Formulas installation and usage instructions.

If you are interested in writing or contributing to formulas, please pay attention to the Writing Formula Section.

If you want to use this formula, please pay attention to the FORMULA file and/or git tag, which contains the currently released version. This formula is versioned according to Semantic Versioning.

See Formula Versioning Section for more details.

If you need (non-default) configuration, please pay attention to the pillar.example file and/or Special notes section.

Commit message formatting is significant!!

Please see How to contribute for more details.

Use the supplied haproxy.cfg for a flat file approach, or the jinja template and the pillar for a salt approach.

Meta-state (This is a state that includes other states).

This installs the haproxy package, manages the haproxy configuration file and then starts the associated haproxy service.

This state will install the haproxy package only.

This state will configure the haproxy service and has a dependency on haproxy.install via include list.

Currently, only a handful of options can be set using the pillar:

  • Global
    • stats: enable stats, currently only via a unix socket which can be set to a path with custom permissions and optional extra bind arguments
    • user: sets the user haproxy shall run as
    • group: sets the group haproxy shall run as
    • chroot: allows you to turn on chroot and set a directory
    • daemon: allows you to turn daemon mode on and off
  • Default
    • log: set the default log
    • mode: sets the mode (i.e. http)
    • retries: sets the number of retries
    • options: an array of options that is simply looped with no special treatment
    • timeouts: an array of timeouts that is simply looped with no special treatment
    • errorfiles: an array of k:v errorfiles to point to the correct file matching an HTTP error code
  • Frontend; Frontend(s) is a list of the frontends you desire to have in your haproxy setup Per frontend you can set:
    • name: the name haproxy will use for the frontend
    • bind: the bind string: this allows you to set the IP, Port and other paramters for the bind
    • redirect: add a redirect line, an unparsed string like in the backend
    • reqadd: an array of reqadd statements. Looped over and put in the configuration, no parsing
    • default_backend: sets the default backend
    • acls: a list of acls, not parsed, simply looped and put in to the configuration
    • blocks: a list of block statements, not parsed, simply looped and put in to the configuration
    • use_backends: a list of use_backend statements, looped over, not parsed
  • Backend; Backend(s) is a list of the backends you desire to have in your haproxy setup, per backend you can set:
    • name: set the backend name, used in the frontend references by haproxy
    • balance: set the balance type, string
    • redirect: if set, can be used to redirect; simply a string, not parsed
    • servers: a list of servers this backend will contact, is looped over; per server you can set:
      • name: name of the server for haproxy
      • host: the host to be contacted
      • port: the port to contact the server on
      • check: set to check to enable checking
  • For global, default, frontend, listener, backend and server it is possible to use the "extra" option for more rare settings not mentioned above.

This state will start the haproxy service and has a dependency on haproxy.config via include list.

Linux testing is done with kitchen-salt.

Requirements

  • Ruby
  • Docker
$ gem install bundler
$ bundle install
$ bin/kitchen test [platform]

Where [platform] is the platform name defined in kitchen.yml, e.g. debian-9-2019-2-py3.

bin/kitchen converge

Creates the docker instance and runs the haproxy main state, ready for testing.

bin/kitchen verify

Runs the inspec tests on the actual instance.

bin/kitchen destroy

Removes the docker instance.

bin/kitchen test

Runs all of the stages above in one go: i.e. destroy + converge + verify + destroy.

bin/kitchen login

Gives you SSH access to the instance for manual testing.

haproxy-formula's People

Contributors

abednarik avatar aboe76 avatar aminet avatar baby-gnu avatar bigbosst avatar bneqld avatar boltronics avatar cp-richard avatar dafyddj avatar daks avatar gravyboat avatar iggy avatar javierbertoli avatar johnkeates avatar kjkeane avatar liunich avatar morsik avatar msciciel avatar myii avatar mymasse avatar nmadhok avatar noelmcloughlin avatar puneetk avatar semantic-release-bot avatar stenstad avatar stp-ip avatar tacerus avatar thatch45 avatar ticosax avatar whiteinge 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

Watchers

 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

haproxy-formula's Issues

copy keepalived config jinja

Would it be better to base the jinja template off the keepalived formula? https://github.com/saltstack-formulas/keepalived-formula/blob/master/keepalived/templates/config.jinja

It seems right now that all the options need to be maintained, but you can't easily add any if they are missing.

Problems may arise from certain settings with periods, which will probably need to be maintained. Example:

  • tune.ssl.maxrecord
  • tune.ssl.default-dh-param
  • tune.ssl.ssl-ctx-cache-size

Are there any foreseeable issues with doing it this way?

running formula with pillar.example failed

Test on Ubuntu 14.04

Error

[ERROR   ] output:  * Starting haproxy haproxy
[ALERT] 267/055217 (17381) : config : no <listen> line. Nothing to do !
[ALERT] 267/055217 (17381) : Fatal errors found in configuration.
   ...fail!

Is that consider an error?

Support backends from salt mine

It would be great if this could support getting backend information from the salt mine.

Here's a quick partial solution that I worked up for my own needs. Adding the key servers_from_mine it will add backends from mine.get 'value' network.ip_addrs. It's only a partial solution as this does not handle specifying port, check, or extra as in the pillar version.

  backends:
    backend1:
      name: www-backend
      balance: roundrobin
      redirects:
        - scheme https if !{ ssl_fc }
      servers_from_mine: 'web*'
diff --git a/haproxy/templates/haproxy.jinja b/haproxy/templates/haproxy.jinja
index ed0a689..9584ebf 100644
--- a/haproxy/templates/haproxy.jinja
+++ b/haproxy/templates/haproxy.jinja
@@ -500,10 +500,17 @@ backend {{ backend.get('name', backend_name) }}
     {%- if 'defaultserver' in backend %}
     default-server {%- for option, value in backend.defaultserver|dictsort %} {{ ' '.join((option, value|string, '')) }} {%- endfor %}
     {%- endif %}
-    {%- if 'servers' in backend %}
-      {%- for server_name, server in backend.servers|dictsort %}
-    server {{ server.get('name', server_name) }} {{ server.host }}{% if 'port' in server %}:{{ server.port }}{% endif %} {{ server.get('check', '') }} {{ server.get('extra', '') }}
+    {%- if 'servers_from_mine' in backend %}
+      {%- set matcher = backend.servers_from_mine %}
+      {%- for server, addrs in salt['mine.get'](matcher, 'network.ip_addrs').items() %}
+      server {{ server }} {{ addrs[0] }}:80 check
       {%- endfor %}
+    {%- else %}
+      {%- if 'servers' in backend %}
+        {%- for server_name, server in backend.servers|dictsort %}
+      server {{ server.get('name', server_name) }} {{ server.host }}{% if 'port' in server %}:{{ server.port }}{% endif %} {{ server.get('check', '') }} {{ server.get('extra', '') }}
+        {%- endfor %}
+      {%- endif %}
     {%- endif %}
   {% endfor %}
 {%- endif %}

way to manage haproxy package repository

Hello,

at the moment, there is no way in the formula to specify from which repository Haproxy package must be installed. The only way is to extend the formula.

I think this is a standard need which can easily be added. I thought about two ways to do it:

  • first one, simply adding a 'haproxy:fromrepo' pillar and in install.sls check if it exists and use it if it does
  • second one, depending of the merge of GH-69, to add a default value in map.jinja and use it. Then allow overriding it with 'haproxy:lookup:fromrepo'

I prefer the second one, which I found prettier and cleanier, but I may not be totally partial :)

I would like to know what people think about it.

Converting inline defaults to defaults.yaml

This is more of a notification than a bug; I'm converting some of the stuff that's gotten to be inline defaults to the slightly more standard (and definitely more flexible) defaults.yaml + map.jinja combination. This came out of my need to install different haproxy versions, i.e. 1.6 via backports and 1.5 on LTS versions of operating systems. I'm also adding initial provisions for an OS Map so you can have different defaults per OS with automated filtering built in.

While this won't break the formula, it might make people with special configs unhappy as some of their defaults they set via the pillar might now be located in a different spot.

I'll try to keep any variable names as they are so most people won't need to do things about their current configs.

Formula broken if overriding map.jinja lookup for the package to install

We are overriding the map.jinja lookup like this to use the Haproxy rpm for version 1.8 from the IUS repository

haproxy:
  lookup:
    package: haproxy18u

This breaks the service.sls haproxy.service state because it references the package using the name not the state id like this:

haproxy.service:
  ...
  -require:
    - pkg: haproxy

Instead of

haproxy.service:
  ...
  -require:
    - pkg: haproxy.install

Also looking I'm pretty sure that the service.dead is also wrong:
Currently:

haproxy.service:
  - service.dead:
    - name: haproxy

When the service name is overriding it won't work unless it is:

haproxy.service:
  - service.dead:
    - name: {{ haproxy.service }}

support for `server-template`

Hi,

I'd like to add a server-template to the backend config to support service discovery from Consul.

It works if I edit the config manually, but if I add it to the Pillar, the formula just ignores it.

Example:

haproxy:
  frontends:
    my_frontend:
      bind:
      - "*:8080"
      default_backend: my_backend

  backends:
    my_backend:
      balance: roundrobin
      server-template: my_backend 1 _service-name._tcp.service.consul resolvers consul resolve-prefer ipv4 check

  resolvers:
    consul:
      options:
      - nameserver consul 127.0.0.1:8600
      - accepted_payload_size 8192
      - hold valid 5s

should render as:

#------------------
# DNS resolvers
#------------------
resolvers consul
    nameserver consul 127.0.0.1:8600
    accepted_payload_size 8192
    hold valid 5s

#------------------
# frontend instances
#------------------
frontend my_frontend
    bind        *:8080
    default_backend my_backend



#------------------
# backend instances
#------------------
backend my_backend
    balance roundrobin
    server-template service-name 1 _service-name._tcp.service.consul resolvers consul resolve-prefer ipv4 check

Many thanks,

Geoff

no http-check in config

would like to check backend servers or listen services for life before routing packets to them.

to acheive this, http-check should be added to config.sls (to complement the settable http-chk option)

Adding support for crt-list

Hi all,

Would it be possible to add support for crt-lists as a state for haproxy. Maybe something like this.

/etc/haproxy/cert-list.txt:
  file.managed:
    - source: salt://haproxy/files/cert-list.txt
    - user: haproxy
    - group: haproxy
    - mode: 640
    - template: jinja
    - defaults:
        certlist: {{ salt['pillar.get']('haproxy:certlist') }}

and the template file would look something like this

{% for domain, cert_location in certlist.iteritems() %}
{{ cert_location }} {{ domain }}
{% endfor %}

Thanks
Fintan

(in)Consistency of pillar keys

I'm thinking about refactoring some of the pillar keys since right now it's a mix of concatenated words, words with dashes and maybe even words with underscores. While it works fine, it's bad in terms of consistency. This means that in practise, a key might have an unexpected spelling and therefore not work at all if one format is presumed but a different non-standard format is used as a pillar key.

I'm suggesting using the same formatting as HAProxy does itself, this way the key consistency (or formatting consistency) is directly derived from HAProxy and thus should match presumptions made from the config documentation. So crt-base will be crt-base in the config and the pillar as well. In the pillar, log-format is log format right now, that would be changed to log-format so the config and pillar match up again.

Another option would be to change all the pillar keys to the same formatting, but right now it's neither and it's inconsistent as a whole. Unless someone is completely against it, I'll change it and merge the updated keys and put in a warning that old config might not work if you use the old keys.

Jinja2 trim_blocks garbles haproxy.jinja

Greetings,

I'm having a strange error with this formula. In a nutshell, having jinja_trim_blocks: True set on my Salt master causes the template haproxy.jinja to spew out a garbled haproxy.cfg file. This results in the service reload failing altogether. Below is an example diff from when I run the command `salt '*' state.highstate test=True':

----------
          ID: haproxy.config
    Function: file.managed
        Name: /etc/haproxy/haproxy.cfg
      Result: None
     Comment: The file /etc/haproxy/haproxy.cfg is set to be changed
     Started: 15:37:09.195603
    Duration: 194.048 ms
     Changes:
              ----------
              diff:
                  ---
                  +++
                  @@ -1,162 +1,33 @@
                  +#------------------
                  +# Global settings
                  +#------------------
                   global
                  - log /dev/log    local0
                  - log /dev/log    local1 notice
                  - chroot /var/lib/haproxy
                  - stats socket /run/haproxy/admin.sock mode 660 level admin
                  - stats timeout 30s
                  - user haproxy
                  - group haproxy
                  - daemon
                  - maxconn 15000
                  - spread-checks 5
                  - tune.ssl.default-dh-param 2048
                  -
                  - # Default SSL material locations
                  - ca-base /etc/ssl/certs
                  - crt-base /etc/ssl/private
                  -
                  - # Default ciphers to use on SSL-enabled listening sockets.
                  - # For more information, see ciphers(1SSL). This list is from:
                  - #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
                  - ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
                  - ssl-default-bind-options no-sslv3 no-tls-tickets no-tlsv10
                  -
                  +    log /dev/log    local0
                  +    log /dev/log    local1 notice
                  +    user haproxy
                  +    group haproxy    chroot  /var/lib/haproxy    daemon    stats socket /run/haproxy/admin.sock level admin    maxconn 15000    spread-checks 5    tune.ssl.default-dh-param 2048    ca-base /etc/ssl/certs    crt-base  /etc/ssl/certs    ssl-default-bind-ciphers  ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS    ssl-default-bind-options   no-sslv3 no-tlsv10 no-tls-tickets#------------------
                  +# Global Userlists
                  +#------------------
                  +userlist companyit_basicauth    user companyIT insecure-password password
                  +#------------------
                  +# common defaults that all the 'listen' and 'backend' sections will
                  +# use- if not designated in their block
                  +#------------------
                   defaults
                  - log global
                  - mode http
                  - option httplog
                  - option dontlognull
                  -     timeout client 60s
                  - timeout connect 9s
                  - timeout server 30s
                  - timeout check 5s
                  - errorfile 400 /etc/haproxy/errors/400.http
                  - errorfile 403 /etc/haproxy/errors/403.http
                  - errorfile 408 /etc/haproxy/errors/408.http
                  - errorfile 500 /etc/haproxy/errors/500.http
                  - errorfile 502 /etc/haproxy/errors/502.http
                  - errorfile 503 /etc/haproxy/errors/503.http
                  - errorfile 504 /etc/haproxy/errors/504.http
                  -
                  -listen stats
                  - bind *:1618
                  - stats enable
                  - mode http
                  - log global
                  - stats show-node
                  - stats uri /
                  - #stats hide-version
                  - stats realm HAProxy\ Statistics
                  - stats auth companyIT:password
                  -
                  -userlist companyit_basicauth
                  - user companyIT insecure-password password
                  -
                  -frontend http-frontend
                  - bind *:80 accept-proxy
                  - reqadd X-Forwarded-Proto:\ http
                  - # Headers and options
                  - option forwardfor
                  - option http-server-close
                  - option httpclose
                  - mode http
                  - # Backend Map
                  - use_backend %[req.hdr(host),lower,map_sub(/etc/haproxy/backend.map,sgt-backend)]
                  -
                  -frontend https-frontend
                  - bind *:443 accept-proxy ssl crt /etc/ssl/pem/ npn spdy/2
                  - # Headers and options
                  - mode http
                  - option forwardfor
                  - option http-server-close
                  - option httpclose
                  - # SSL Options
                  - rspadd Strict-Transport-Security:\ max-age=31536000;\ includeSubdomains;\ preload
                  - rspadd X-Frame-Options:\ DENY
                  - reqadd X-Forwarded-Proto:\ https
                  - # Backend Map
                  - use_backend %[req.hdr(host),lower,map_sub(/etc/haproxy/backend.map,sgt-backend)]
                  -
                  -backend ipmgmt-backend
                  - mode http
                  - acl ipmgmt_network_allowed src -f /etc/haproxy/company-office-ips.map
                  - http-request deny if !ipmgmt_network_allowed
                  - redirect scheme https code 301 if !{ ssl_fc }
                  - balance leastconn
                  - option forwardfor
                  - option redispatch
                  - option abortonclose
                  - option http-server-close
                  - server ipmgmt-app-01-live 10.0.10.5:80 check
                  -
                  -backend jenkins-backend
                  - mode http
                  - redirect scheme https code 301 if !{ ssl_fc }
                  - balance leastconn
                  - option forwardfor
                  - option redispatch
                  - option abortonclose
                  - option http-server-close
                  - server deploy-webjava-01-live 10.0.20.10:8080 check
                  -
                  -backend status-backend
                  - mode http
                  - acl network_allowed src -f /etc/haproxy/company-office-ips.map
                  - http-request deny if !network_allowed
                  - redirect scheme https code 301 if !{ ssl_fc }
                  - balance leastconn
                  - option forwardfor
                  - option redispatch
                  - option abortonclose
                  - option http-server-close
                  - server status-app-01-live 10.0.10.107:80 check
                  -
                  -backend sentry-backend
                  - mode http
                  - redirect scheme https code 301 if !{ ssl_fc }
                  - balance leastconn
                  - option forwardfor
                  - option redispatch
                  - option abortonclose
                  - option http-server-close
                  - server sentry-app-01-live 10.0.10.70:80 check
                  -
                  -backend sgt-backend
                  - mode http
                  - balance leastconn
                  - option forwardfor
                  - option redispatch
                  - option abortonclose
                  - option http-server-close
                  - server sgt-app-01-live 10.0.15.39:80 check
                  -
                  -
                  -backend piwik-backend
                  - mode http
                  - redirect scheme https code 301 if !{ ssl_fc }
                  - balance leastconn
                  - option forwardfor
                  - option redispatch
                  - option abortonclose
                  - option http-server-close
                  - server piwik-app-01-live 10.0.10.126:80 check
                  -
                  -
                  +    log global
                  +    mode http
                  +    retries 3
                  +    balance roundrobin    hash-type map-based    option  httplog    option   dontlognull    option   forwardfor    option    http-server-close    option redispatch    option    abortonclose    log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r    timeout http-request    10s    timeout queue           1m    timeout connect         10s    timeout client          1m    timeout server          30s    timeout http-keep-alive 10s    timeout check           10s    errorfile 400 /etc/haproxy/errors/400.http    errorfile 403 /etc/haproxy/errors/403.http    errorfile 408 /etc/haproxy/errors/408.http    errorfile 500 /etc/haproxy/errors/500.http    errorfile 502 /etc/haproxy/errors/502.http    errorfile 503 /etc/haproxy/errors/503.http    errorfile 504 /etc/haproxy/errors/504.http
                  +#------------------
                  +# listen instances
                  +#------------------listen stats    bind *:1618    mode http    stats auth companyIT:password    stats enable    stats hide-version     stats realm HAProxy\ Statistics    stats refresh 20s    stats show-node     stats uri /
                  +#------------------
                  +# frontend instances
                  +#------------------frontend http-frontend    bind    *:80 accept-proxy    reqadd X-Forwarded-Proto:\ http    use_backend %[req.hdr(host),lower,map_sub(/etc/haproxy/backend.map,sgt-backend)]  frontend https-frontend    bind   *:443 accept-proxy ssl crt /etc/ssl/pem/ npn spdy/2    log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r\ ssl_version:%sslv\ ssl_cipher:%sslc    rspadd    Strict-Transport-Security:\ max-age=31536000;\ includeSubdomains;\ preload    rspadd    X-Frame-Options:\ DENY    reqadd    X-Forwarded-Proto:\ https    use_backend    %[req.hdr(host),lower,map_sub(/etc/haproxy/backend.map,sgt-backend)]
                  +#------------------
                  +# backend instances
                  +#------------------backend ipmgmt-backend    balance leastconn    acl    network_allowed src -f /etc/haproxy/company-office-ips.map    http-request deny if !network_allowed    redirect scheme https code 301 if !{ ssl_fc }    server ipmgmt-app-01-live 10.0.10.5:80 check   backend jenkins-backend    balance leastconn    redirect scheme https code 301 if !{ ssl_fc }    server deploy-webjava-01-live 10.0.20.10:8080 check   backend piwik-backend    balance leastconn    redirect scheme https code 301 if !{ ssl_fc }    server piwik-app-01-live 10.0.10.126:80 check   backend sentry-backend    balance leastconn    redirect scheme https code 301 if !{ ssl_fc }    server sentry-app-01-live 10.0.10.70:80 check   backend sgt-backend    balance leastconn    server sgt-app-01-live 10.0.15.39:80 check   backend status-backend    balance leastconn    acl    network_allowed src -f /etc/haproxy/company-office-ips.map    http-request deny if !network_allowed    redirect scheme https code 301 if !{ ssl_fc }    server status-app-01-live 10.0.10.107:80 check
  Name: /etc/haproxy/company-office-ips.map - Function: file.managed - Result: Clean
  Name: /etc/haproxy/blocked-ips.map - Function: file.managed - Result: Clean

In short, it's a huge mess that HAProxy doesn't like at all, and complains about if you try to restart. Setting jinja_trim_blocks: False seems to solve the problem, but it seems like a weird fix. Here are my respective versioning reports:

Master:

Salt Version:
           Salt: 2015.8.8

Dependency Versions:
         Jinja2: 2.7.2
       M2Crypto: Not Installed
           Mako: 0.9.1
         PyYAML: 3.11
          PyZMQ: 14.0.1
         Python: 2.7.6 (default, Jun 22 2015, 17:58:13)
           RAET: Not Installed
        Tornado: 4.2.1
            ZMQ: 4.0.4
           cffi: Not Installed
       cherrypy: Not Installed
       dateutil: 2.4.2
          gitdb: 0.5.4
      gitpython: 0.3.2 RC1
          ioflo: Not Installed
        libgit2: Not Installed
        libnacl: Not Installed
   msgpack-pure: Not Installed
 msgpack-python: 0.3.0
   mysql-python: 1.2.3
      pycparser: Not Installed
       pycrypto: 2.6.1
         pygit2: Not Installed
   python-gnupg: Not Installed
          smmap: 0.8.2
        timelib: Not Installed

System Versions:
           dist: Ubuntu 14.04 trusty
        machine: x86_64
        release: 3.13.0-83-generic
         system: Ubuntu 14.04 trusty

HAProxy Minion:

Salt Version:
           Salt: 2015.8.8.2

Dependency Versions:
         Jinja2: 2.7.2
       M2Crypto: Not Installed
           Mako: 0.9.1
         PyYAML: 3.10
          PyZMQ: 14.0.1
         Python: 2.7.6 (default, Jun 22 2015, 17:58:13)
           RAET: Not Installed
        Tornado: 4.2.1
            ZMQ: 4.0.4
           cffi: Not Installed
       cherrypy: Not Installed
       dateutil: 1.5
          gitdb: Not Installed
      gitpython: Not Installed
          ioflo: Not Installed
        libgit2: Not Installed
        libnacl: Not Installed
   msgpack-pure: Not Installed
 msgpack-python: 0.3.0
   mysql-python: 1.2.3
      pycparser: Not Installed
       pycrypto: 2.6.1
         pygit2: Not Installed
   python-gnupg: Not Installed
          smmap: Not Installed
        timelib: Not Installed

System Versions:
           dist: Ubuntu 14.04 trusty
        machine: x86_64
        release: 3.13.0-83-generic
         system: Ubuntu 14.04 trusty

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.