Giter VIP home page Giter VIP logo

puppet-wildfly's Introduction

wildfly

License puppetmodule.info docs CI Donated by biemond

Puppet Forge Endorsement Puppet Forge Version Puppet Forge Score Puppet Forge Downloads

Table of Contents

  1. Overview
  2. Module Description - What the module does and why it is useful
  3. Setup - The basics of getting started with wildfly
  4. Upgrade
  5. Usage - Configuration options and additional functionality
  6. Limitations - OS compatibility, etc.
  7. Development - Guide for contributing to the module
  8. Documentation

Overview

Originally created by Edwin Biemond email biemond at gmail dot com biemond.blogspot.com

Install, configures and manages Wildfly.

Should work on every Redhat or Debian family member, tested with Wildfly 10.1, 10.0, 9.0, 8.2, 8.1 & 8.0 and with JBoss EAP (tested on 6.1/6.2/6.3/6.4 and 7.0). Some defines may work only in certain versions.

Vagrant Fedora 21, Puppet 4.2.1 example with Wildfly 8.2, Apache AJP and PostgreSQL.

Vagrant CentOS Standalone HA + Gossip Router example with two nodes, a gossip router and a load balancer (httpd + mod_cluster).

Vagrant CentOS 7.2 Domain Mode with two nodes (Domain master and slave) and a load balancer.

Module Description

The wildfly module can install, configure and manage - through its HTTP Management API - Wildfly (8/9/10+) and JBoss EAP (6.1+/7.0+).

Setup

What wildfly affects

  • Manage Wildfly user, group and directory.

  • Creates a wildfly service using bundled scripts and manages its installation and resources (using Management API)

  • Installs requisite libaio and wget packages

Setup Requirements

This module requires a JVM ( should already be there ). Just need to be extracted somewhere, no need to update-alternatives, set PATH or anything else, but it also works if you choose to do so.

Three gems are bundled with this module: treetop (parsing JBoss-CLI commands), polyglot (treetop's requirement) and net-http-digest_auth (Management API authentication).

Acceptance tests works with puppetlabs/java in both CentOS and Debian.

This module requires puppetlabs-stdlib and jethrocarr/initfact (it uses init_system fact provided by this module by default, but it's overridable in wildfly::initsystem parameter)

It should work on every operating system with the following init systems: sysvinit, systemd and upstart

Upgrade

to 1.2.0

wildfly class

The main changes in wildfly class are below:

class { 'wildfly':
  distribution     => 'jboss-eap|wildfly',
  properties       => {
    'jboss.bind.address'            => $public_bind,
    'jboss.bind.address.management' => $mgmt_bind,
    'jboss.management.http.port'    => $mgmt_http_port,
    'jboss.management.https.port'   => $mgmt_https_port,
    'jboss.http.port'               => $public_http_port,
    'jboss.https.port'              => $public_https_port,
    'jboss.ajp.port'                => $ajp_port,
  },
  jboss_opts       => '-Dproperty=value'
  mgmt_user        => { username  => $management_user, password  => $management_password },
}

distribution was introduced to provide out of the box support for JBoss EAP and properties to replace fine-grained parameters for address/port binding like public_bind, mgmt_bind and public_http_port. (Reason: It's easier - and more reliable - to manage a properties file than Wildfly's XML through augeas)

users_mgmt was replaced by mgmt_user, and additional users should be managed by wildfly::config::mgtm_user defined type. The hash format and default value also changed.

New dependency

jethrocarr/initfact module.

Defined types

All resources from wildfly::util were moved to wildfly, hence you need to search and replace them, I suggest you execute these commands in your environment:

find . -name '*.pp' -type f -exec sed -i 's/wildfly::util::exec_cli/wildfly::cli/g' {} +

find . -name '*.pp' -type f -exec sed -i 's/wildfly::util/wildfly/g' {} +

to 2.0.0

This version requires Puppet 4.4+ and heavily uses Puppet 4 new features: data types, epp templates and Ruby 2.1+, but there is no breaking change per se. Meaning that if you're using 1.x version with Puppet 4 you should be able to migrate without any problems.

If you're still using Puppet 3.x with Ruby 1.8.7+ check version 1.2.x (unsupported).

to 2.1.0

This version will no longer stringify values for wildfly_resource's state or sort arrays values. In other words, you'll have to declare attributes using a type that matches Wildfly's Management Model type and in the same order returned by the API (in case of an array/LIST).

Usage

class { 'wildfly': }

Wildfly 25.0.0

class { 'wildfly':
  version           => '25.0.0',
  init_system       => 'systemd',
  install_source    => 'https://github.com/wildfly/wildfly/releases/download/25.0.0.Final/wildfly-25.0.0.Final.tar.gz',
  install_cache_dir => '/tmp',
  java_home         => '/usr/lib/jvm/java-17-openjdk-amd64',
}

Wildfly 23.0.2

class { 'wildfly':
  version           => '23.0.2',
  init_system       => 'systemd',
  install_source    => 'https://download.jboss.org/wildfly/23.0.2.Final/wildfly-23.0.2.Final.tar.gz',
  install_cache_dir => '/tmp',
  java_home         => '/usr/lib/jvm/java-17-openjdk-amd64',
}

Wildfly 10.1.0

class { 'wildfly':
  version        => '10.1.0',
  install_source => 'http://download.jboss.org/wildfly/10.1.0.Final/wildfly-10.1.0.Final.tar.gz',
}

Wildfly 9.0.2

class { 'wildfly':
  version        => '9.0.2',
  install_source => 'http://download.jboss.org/wildfly/9.0.2.Final/wildfly-9.0.2.Final.tar.gz',
}

Wildfly 8.2.1

class { 'wildfly':
  version        => '8.2.1',
  install_source => 'http://download.jboss.org/wildfly/8.2.1.Final/wildfly-8.2.1.Final.tar.gz',
}

JBoss EAP 6.x (with hiera)

include wildfly
wildfly::distribution: 'jboss-eap'
wildfly::version: '6.4'
wildfly::install_source: 'http://mywebserver/jboss-eap-6.4.tar.gz'
wildfly::user: 'jboss-as'
wildfly::group: 'jboss-as'
wildfly::dirname: '/opt/jboss-as'
wildfly::console_log: '/var/log/jboss-as/console.log'

JBoss EAP 7.0

class { 'wildfly':
  version        => '7.0',
  distribution   => 'jboss-eap',
  install_source => 'http:/mywebserver/jboss-eap-7.0.tar.gz',
  user           => 'jboss-eap',
  group          => 'jboss-eap',
  dirname        => '/opt/jboss-eap',
  console_log    => '/var/log/jboss-eap/console.log',
}

Keycloak

Keycloak is an open source Identity and Access Management built on top of Wildfly/JBoss platform, therefore you should be able to use this module to install and config it.

class { 'wildfly':
  version        => '10.1.0',
  distribution   => 'wildfly',
  install_source => 'https://downloads.jboss.org/keycloak/2.5.0.Final/keycloak-2.5.0.Final.tar.gz',
}

NOTE: Just make sure to point to the right version/distribution it was built upon.

Some Keycloak configuration can be managed in the same way as a regular Wildfly/Jboss configuration:

wildfly::datasources::datasource { 'KeycloakDS':
  config => {
    'driver-name'    => 'postgresql',
    'password'       => 'keycloak',
    'user-name'      => 'keycloak',
    'jndi-name'      => 'java:jboss/datasources/KeycloakDS',
    'connection-url' => "jdbc:postgresql://192.168.33.20:5432/keycloak",
    'background-validation' => true,
    'background-validation-millis' => 60000,
    'check-valid-connection-sql' => 'SELECT 1',
    'flush-strategy' => 'IdleConnections',
  }
}

apiman

apiman is an API Manager built on top of Wildfly/JBoss, therefore you should be able to use this module to install and config it.

Currently there aren't no prebuilt packages, but download page provides instruction to build it for Wildfly 10, 9 and EAP 7.

Example

wget http://download.jboss.org/wildfly/10.1.0.Final/wildfly-10.1.0.Final.zip
wget http://downloads.jboss.org/apiman/1.2.9.Final/apiman-distro-wildfly10-1.2.9.Final-overlay.zip
unzip wildfly-10.1.0.Final.zip
unzip -o apiman-distro-wildfly10-1.2.9.Final-overlay.zip -d wildfly-10.1.0.Final
tar czvf apiman-wildfly-10.1.0.Final.tar.gz wildfly-10.1.0.Final
class { 'wildfly':
  version        => '10.1.0',
  distribution   => 'wildfly',
  config         => 'standalone-apiman.xml',
  install_source => 'http://10.0.2.2:9090/apiman-wildfly-10.1.0.Final.tar.gz',
}

NOTE: Just make sure to point to the right version/distribution it was built upon.

Infinispan Server

Infinispan Server (or JBoss Data Grid) also work with this module but requires more tweaks.

From Infinispan Server 7 to 9 (including JDG 7.0) you will only need to change install_source to match the desired version:

class { 'wildfly':
  install_source => 'http://10.0.2.2:9090/infinispan-server-8.2.5.Final.tar.gz',
  conf_file      => '/etc/infinispan-server/infinispan-server.conf',
  conf_template  => 'wildfly/infinispan-server.conf.erb',
  service_file   => 'bin/init.d/infinispan-server.sh',
  service_name   => 'infinispan-server',
}

Limitation: You need to repackage it to a tar.gz file and Infinispan Server 6 and JDG 6.x are not working.

Wildfly's Configuration Management

Wildfly has a Management Model that describes its configuration and there are three main elements that you need to understand in order to use this module: path, attributes and operations

This module provides a few defined types built around these concepts using wildfly_resource and wildfly_cli (wildfly::messaging::*, wildfly:datasources::datasource, wildfly:datasources::driver) to ease management of most used resources, but they are not guaranteed to work across all versions of JBoss/Wildfly and they represent only a tiny subset of the Management Model.

In order to manage virtually any configuration in the Model Reference (i.e. datasources, https, queues, modcluster) with wildfly::resource or wildfly::cli you must understand how declared resources are converted to Management API requests using paths, attributes and operations.

Path/Addresss: The resource address in /node-type=node-name (/node-type=node-name)* format. (e.g. /subsystem=datasources/datasource=DatasourceName)

Attributes: key-value pairs that describes the resource. (e.g. driver-name=postgresql, connection-url=jdbc:postgresql://localhost/postgres)

Operations: An operation to be performed in a resource. (e.g. read, write-attribute, remove)

With wildfly::cli you have more control, but you should only use it when you can't manage the resource with wildfly_resource (e.g. you can't manage enabled attribute as it is only changed as a result of enable and disable operations.):

wildfly::cli { "Enable ADatasource":
  command => "/subsystem=datasources/data-source=ADatasource:enable",
  unless  => "(result == true) of /subsystem=datasources/data-source=ADatasource:read-attribute(name=enabled)",
}

For all other scenarios, wildfly::resource will be your best friend, from the most simple resource:

wildfly::resource { "/system-property=myproperty":
  content => {
    'value' => '1234'
  },
}

To the most complex:

wildfly::resource { '/subsystem=modcluster/mod-cluster-config=configuration':
  recursive => true,
  content   => {
        'advertise'             => true,
        'connector'             => 'ajp',
        'excluded-contexts'     => 'ROOT,invoker,jbossws,juddi,console',
        'proxy-url'             => '/',
        'sticky-session'        => true,
        'proxies'               => ['192.168.1.1:6666', '192.168.1.2::6666']
        'balancer'              => 'mybalancer',
        'load-balancing-group'  => 'mygroup',
        'dynamic-load-provider' => {'configuration' => {
            'load-metric' => {'busyness' => {
                'type' => 'busyness',
            }}
        }},
    }
}

The first thing to note about wildfly::resource is the absence of an operation, as you will only need to set ensure with either present or absent, using the first will result in the creation or update of the resource with the declared state/content, whereas the other will remove the resource with all its children.

A resource attribute behaviors like a Puppet resource property. Therefore, unmanaged attributes behavior like unmanaged properties in puppet resources, meaning: if you don't declare, you don't care.

NOTE: Be careful with the type of declared attribute's value as it should match Management Model type. Valid Management Model types include: STRING, INT, BOOLEAN, LIST (i.e. arrays []) and OBJECT (i.e. hashes {}).

Patch management

Wildfly/JBoss allows you to apply patches to existing installation in order to update it. I suggest you use puppet-archive or any other archive module to download patches from remote sources, just be aware that you need to extract patch zip file in order to apply patches to Wildfly, but you'll be able to apply the zip file directly when you're using EAP.

NOTE: Wildfly from versions 8.0.0 to 9.0.1 has a bug in jboss-cli.sh WFCORE-160 that makes it report that a patch hasn't been successfuly applied (exit code 2) even when it was. If you're using one of theses versions you better update this file or live with a bad report.

Offline

Offline patching requires the server to be down, but don't leave the server in a restart-required state.

EAP/Offline example
class { 'wildfly':
  distribution   => 'jboss-eap',
  version        => '6.4',
}

archive { '/opt/wildfly/jboss-eap-6.4.8-patch.zip':
  ensure => present,
  source => 'http://10.0.2.2:9090/jboss-eap-6.4.8-patch.zip',
}
->
wildfly::patch::offline { '6.4.8':
  source => '/opt/wildfly/jboss-eap-6.4.8-patch.zip',
}

Online

Online patching requires the server to be up and requires a restart after being applied.

Wildfly/Online example
class { 'wildfly':
  version        => '10.0.0',
  install_source => 'http://download.jboss.org/wildfly/10.0.0.Final/wildfly-10.0.0.Final.tar.gz',
}

archive { '/opt/wildfly/wildfly-10.1.0.Final-update.zip':
  ensure       => present,
  extract      => true,
  extract_path => '/opt/wildfly',
  creates      => '/opt/wildfly/wildfly-10.1.0.Final.patch',
  source       => 'http://download.jboss.org/wildfly/10.1.0.Final/wildfly-10.1.0.Final-update.zip',
  user         => 'wildfly',
  group        => 'wildfly',
  require      => [File['/opt/wildfly'],Package['unzip']],
}
->
wildfly::patch::online { '10.1.0':
  source       => '/opt/wildfly/wildfly-10.1.0.Final.patch',
  override_all => true,
}

Unmanaged installation

If you don't want to use this module to manage your Wildfly/JBoss installation or you don't want to manage your installation with Puppet at all. You still can use this module to manage your configuration using wildfly_resource, wildfly_cli, wildfly_deployment and wildfly_restart.

Example:

wildfly_resource { "/subsystem=datasources/data-source=MyDS":
  ensure            => 'present',
  username          => 'admin',
  password          => 'password',
  host              => '192.168.33.10',
  port              => '9990',
  state             => {
    'driver-name'    => 'postgresql',
    'connection-url' => 'jdbc:postgresql://localhost/postgres',
    'jndi-name'      => 'java:jboss/datasources/MyDS',
    'user-name'      => 'postgres',
    'password'       => 'postgres',
  },
}

Domain Mode

Master (Domain Controller)

class { 'wildfly':
  mode        => 'domain',
  host_config => 'host-master.xml',
  properties  => {
    'jboss.bind.address.management' => '172.17.0.2',
  },
}

wildfly::config::mgmt_user { 'slave1':
  password => 'wildfly',
}

NOTE: Don't forget to set target_profile while managing your domain resources.

Slave (Host Controller)

class { 'wildfly':
    mode         => 'domain',
    host_config  => 'host-slave.xml',
    properties   => {
      'jboss.domain.master.address' => '172.17.0.2',
    },
    secret_value => 'd2lsZGZseQ==', #base64('wildfly'),
}

NOTE: Host Controller name has to match a mgmt user name in Domain Controller, since, by default, HC uses it own name as the username for connecting with DC. You can always set a different one by overriding remote_username parameter.

Domain Management

Make sure you remove default resources (server-groups and server-config) if you're not going to use it.

Domain controller:

wildfly::domain::server_group { ['main-server-group', 'other-server-group']:
  ensure => absent,
}

Host controller:

wildfly::host::server_config { ['server-one', 'server-two']:
 ensure   => absent,
 hostname => $hostname,
 username => $username,
 password => $password,
 before   => Class['wildfly::setup'],
}

You can also use a overlay_class instead of use before.

Host controller:

class { 'wildfly':
  # ...
  overlay_class => 'app::cleanup'
}

class app::cleanup {
  wildfly::host::server_config { ['server-one', 'server-two']:
   ensure   => absent,
   hostname => $hostname,
   username => $username,
   password => $password,
  }
}

Username and password are the credentials used to connect to domain controller and make the desired changes. In the first provision this resource will be applied with augeas and will not need that, but in the other these parameters will be required to guarantee that the server-configs no longer exists.

After that, start managing your own server-groups and server-config with wildfly::domain::server-group and wildfly::host::server_config:

Domain controller:

wildfly::domain::server_group { 'app-server-group':
  profile              => 'full-ha',
  socket_binding_group => 'full-ha-sockets',
}

Host controller:

wildfly::host::server_config { 'app':
  server_group       => 'app-server-group',
  hostname           => $hostname,
  username           => $username,
  password           => $password,
}

Please note that you'll need to enable external facts (wildfly::external_facts) since wildfly::host::server_config relies on wildfly_is_running fact to know if it should use augeas or connect to the domain controller to remove a server-config.

Custom Java options

Domain controller:

class { 'wildfly':
  ...,
  java_opts                    => ['<java_opt_1>', '<java_opt_2>']
  process_controller_java_opts => ['<controller_opt_1>', '<controller_opt_2>']
}

Results in a domain.conf with:

if [ "x$JAVA_OPTS" = "x" ]; then
    JAVA_OPTS=...
    JAVA_OPTS="$JAVA_OPTS <java_opt_1> <java_opt_2>"
    ...
fi
...
if [ "x$PROCESS_CONTROLLER_JAVA_OPTS" = "x" ]; then
    PROCESS_CONTROLLER_JAVA_OPTS="$JAVA_OPTS <controller_opt_1>, <controller_opt_2>"
fi

Host controller:

class { 'wildfly':
  ...,
  java_opts                 => ['<java_opt_1>', '<java_opt_2>']
  host_controller_java_opts => ['<managed_opt_1>', '<managed_opt_2>']
}

Results in a domain.conf with:

if [ "x$JAVA_OPTS" = "x" ]; then
    JAVA_OPTS=...
    JAVA_OPTS="$JAVA_OPTS <java_opt_1> <java_opt_2>"
    ...
fi
...
if [ "x$HOST_CONTROLLER_JAVA_OPTS" = "x" ]; then
    HOST_CONTROLLER_JAVA_OPTS="$JAVA_OPTS <managed_opt_1> <managed_opt_2>"
fi

Java Virtual Machine options

To adjust JVM heap memory settings, use wildfly class java_xmx, java_xms and/or java_maxmetaspace_size parameters:

class { 'wildfly':
  # ...
  java_xms               => '<Minimum heap size>',
  java_xmx               => '<Maximum heap size>',
  java_maxmetaspace_size => '<Maximum Metaspace size>',
}

Deployment

From a local or remote source

Source supports these protocols: http://, ftp://, puppet://, file://

wildfly::deployment { 'hawtio.war':
 source => 'http://central.maven.org/maven2/io/hawt/hawtio-web/1.4.48/hawtio-web-1.4.48.war',
}
wildfly::deployment { 'hawtio.war':
 source => 'puppet:///modules/profile/wildfly/hawtio-web-1.4.48.war',
}
wildfly::deployment { 'hawtio.war':
 source => 'file://var/tmp/hawtio-web-1.4.48.war',
}

To a target server-group (domain mode)

wildfly::deployment { 'hawtio.war':
 source       => 'http://central.maven.org/maven2/io/hawt/hawtio-web/1.4.48/hawtio-web-1.4.48.war',
 server_group => 'main-server-group',
}

From nexus

NOTE: This feature was removed to avoid 'archive' name collision, but you can still use archive::nexus to download an artifact and use as an input for wildfly::deployment

archive::nexus { '/tmp/hawtio.war':
  url        => 'https://oss.sonatype.org',
  gav        => 'io.hawt:hawtio-web:1.4.66',
  repository => 'releases',
  packaging  => 'war',
}
~>
wildfly::deployment { 'hawtio.war':
  source => '/tmp/hawtio.war'
}

User management

You can add App and Management users (requires server restart).

wildfly::config::mgmt_user { 'mgmtuser':
  password => 'mgmtuser'
}
wildfly::config::app_user { 'appuser':
  password => 'appuser'
}

And associate groups or roles to them (requires server restart)

wildfly::config::user_groups { 'mgmtuser':
  groups => 'admin,mygroup'
}
wildfly::config::user_roles { 'appuser':
  roles => 'guest,ejb'
}

Module installation

Install a JAR module from a remote file system, puppet file server or local file system.

wildfly::config::module { 'org.postgresql':
  source       => 'http://central.maven.org/maven2/org/postgresql/postgresql/9.3-1103-jdbc4/postgresql-9.3-1103-jdbc4.jar',
  dependencies => ['javax.api', 'javax.transaction.api']
}
wildfly::config::module { 'org.postgresql':
  source       => 'puppet:///modules/profiles/wildfly/postgresql-9.3-1103-jdbc4.jar',
  dependencies => ['javax.api', 'javax.transaction.api']
}
wildfly::config::module { 'org.postgresql':
  source       => 'file:///var/tmp/postgresql-9.3-1103-jdbc4.jar',
  dependencies => ['javax.api', 'javax.transaction.api']
}

Datasources

Setup a driver and a datasource (for domain mode you need to set target_profile parameter):

wildfly::datasources::driver { 'Driver postgresql':
  driver_name                     => 'postgresql',
  driver_module_name              => 'org.postgresql',
  driver_xa_datasource_class_name => 'org.postgresql.xa.PGXADataSource'
}
->
wildfly::datasources::datasource { 'DemoDS':
  config         => {
    'driver-name'    => 'postgresql',
    'connection-url' => 'jdbc:postgresql://localhost/postgres',
    'jndi-name'      => 'java:jboss/datasources/DemoDS',
    'user-name'      => 'postgres',
    'password'       => 'postgres'
  }
}

Alternatively, you can install a JDBC driver and module using deployment if your driver is JDBC4 compliant:

wildfly::deployment { 'postgresql-9.3-1103-jdbc4.jar':
  source => 'http://central.maven.org/maven2/org/postgresql/postgresql/9.3-1103-jdbc4/postgresql-9.3-1103-jdbc4.jar'
}
->
wildfly::datasources::datasource { 'DemoDS':
  config         => {
    'driver-name'    => 'postgresql-9.3-1103-jdbc4.jar',
    'connection-url' => 'jdbc:postgresql://localhost/postgres',
    'jndi-name'      => 'java:jboss/datasources/DemoDS',
    'user-name'      => 'postgres',
    'password'       => 'postgres'
  }
}

A postgresql normal & XA datasource example

wildfly::config::module { 'org.postgresql':
  source       => 'http://central.maven.org/maven2/org/postgresql/postgresql/9.3-1103-jdbc4/postgresql-9.3-1103-jdbc4.jar',
  dependencies => ['javax.api', 'javax.transaction.api'],
  require      => Class['wildfly'],
}
->
wildfly::datasources::driver { 'Driver postgresql':
  driver_name                     => 'postgresql',
  driver_module_name              => 'org.postgresql',
  driver_xa_datasource_class_name => 'org.postgresql.xa.PGXADataSource'
}
->
wildfly::datasources::datasource { 'petshop datasource':
  name           => 'petshopDS',
  config         => { 'driver-name'    => 'postgresql',
                      'connection-url' => 'jdbc:postgresql://10.10.10.10/petshop',
                      'jndi-name'      => 'java:jboss/datasources/petshopDS',
                      'user-name'      => 'petshop',
                      'password'       => 'password'
                    }
}
->
wildfly::datasources::xa_datasource { 'petshopDSXa':
  config          => {  'driver-name'              => 'postgresql',
                        'jndi-name'                => 'java:jboss/datasources/petshopDSXa',
                        'user-name'                => 'petshop',
                        'password'                 => 'password',
                        'xa-datasource-class'      => 'org.postgresql.xa.PGXADataSource',
                        'xa-datasource-properties' => {
                              'url' => {'value' => 'jdbc:postgresql://10.10.10.10/petshop'}
                        },
  }
}

Datasource configuration uses a hash with elements that match JBoss-CLI datasource add elements name.

Configure Database Property, only works for normal datasources

wildfly::datasources::db_property { 'DemoDbProperty':
 value    => 'demovalue',
 database => 'ExampleDS',
}

HTTPS/SSL

Wildfly 8+

wildfly::undertow::https { 'https':
  socket_binding    => 'https',
  keystore_path     => '/vagrant/identitystore.jks',
  keystore_password => 'changeit',
  key_alias         => 'demo',
  key_password      => 'changeit'
}

JBoss AS7/EAP 6

wildfly::web::connector { 'https':
  scheme         => 'https',
  protocol       => 'HTTP/1.1',
  socket_binding => 'https',
  enable_lookups => false,
  secure         => true,
}
->
wildfly::web::ssl { 'ssl':
  connector            => 'https',
  protocol             => 'TLSv1,TLSv1.1,TLSv1.2',
  password             => 'changeit',
  key_alias            => 'demo',
  certificate_key_file => '/opt/identitykeystore.jks',
  cipher_suite         => 'TLS_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA',
}

Sample identity store configuration with puppetlabs-java_ks

java_ks { 'demo:/opt/identitystore.jks':
  ensure      => latest,
  certificate => '/opt/demo.pub.crt',
  private_key => '/opt/demo.private.pem',
  path        => '/usr/java/jdk1.7.0_75/bin/',
  password    => 'changeit',
}

Management over HTTPS/SSL

This feature is currently implemented for standalone mode only. The default http management console and API can be changed to run over HTTPS/TLS.

Basic use with a self signed certificate

This will generate and use a basic self signed certificate for the Management interface. Requires the puppetlabs/java_ks module:

class { 'wildfly':
	secure_mgmt_api => true,
}

Providing your own certificate

The module will create the approprate keystores, truststores, and configuration if given paths to the private key and certificate. Use your favorite method to ensure the key and certificate exist on the endpoint. Requires the puppetlabs/java_ks module:

class { 'wildfly':
	secure_mgmt_api => true,
	mgmt_ssl_key => '/etc/pki/tls/private/key.pem',
	mgmt_ssl_cert => '/etc/pki/tls/certs/cert.pem',
}

Unmanaged keystores

If preferred, the management API can be configured to use keystores/truststores managed outside this module. These will need to exist before running the wildfly class.

Be aware of the following:

  • The existing keystore needs to be readable by the wildfly user.
  • Truststores need to exist in the home directories for the wildfly user and the root user.
class { 'wildfly':
	secure_mgmt_api => true,
    mgmt_create_keystores => false,
    mgmt_keystore => '/etc/pki/keystores/wf_ks.jks',
	mgmt_keystore_pass => 'password',
	mgmt_keystore_alias => 'wfmgmt',
}

Server Reload

Some configurations like SSL and modcluster requires a server reload (i.e. server-state = reload-required), and it can be achieved with the following snippet:

## a_resource_that_requires_reload_when_changed {}
~>
wildfly::reload { 'Reload if necessary':
  retries => 2,
  wait    => 15,
}

Or

wildfly::cli { 'Reload if necessary':
  command => ':reload',
  onlyif  => '(result == reload-required) of :read-attribute(name=server-state)'
}

Even operation-headers can do the trick in some cases:

wildfly::resource { '/some=resource':
  operation_headers => {
    'allow-resource-service-restart' => true,
  }
}

Messaging

NOTE: full profiles only

wildfly::messaging::queue { 'DemoQueue':
  durable  => true,
  entries  => ['java:/jms/queue/DemoQueue'],
  selector => "MessageType = 'AddRequest'"
}

wildfly::messaging::topic { 'DemoTopic':
  entries => ['java:/jms/topic/DemoTopic']
}

Wildfly 10/EAP 7+ replaced HornetQ with ActiveMQ and queue/topic management is slightly different:

wildfly::messaging::activemq::queue { 'DemoQueue':
  durable  => true,
  entries  => ['java:/jms/queue/DemoQueue'],
  selector => "MessageType = 'AddRequest'"
}

wildfly::messaging::activemq::topic { 'DemoTopic':
  entries => ['java:/jms/topic/DemoTopic']
}

Logging

wildfly::logging::category { 'DemoCategory':
  level               => 'DEBUG',
  use_parent_handlers => false,
  handlers            =>  ['DemoHandler']
}

System Property

wildfly::system::property { 'DemoSysProperty':
 value => 'demovalue'
}

Modcluster

NOTE:full and ha profiles only

wildfly::modcluster::config { "Modcluster mybalancer":
  balancer             => 'mybalancer',
  load_balancing_group => 'demolb',
  proxy_url            => '/',
  proxy_list           => '127.0.0.1:6666'
}

NOTE: For apache/httpd mod_cluster configuration check ::apache::mod::cluster

JGroups

NOTE: ha profiles only

wildfly::jgroups::stack::tcpgossip { 'TCPGOSSIP':
  initial_hosts       => '172.28.128.1[12001]',
  num_initial_members => 2
}
wildfly::jgroups::stack::tcpping { 'TCPPING':
  initial_hosts       => '172.28.128.10[7600],17228.128.20[7600]',
  num_initial_members => 2
}

Limitations

Some of this module public defined types (widfly::datasources, wildfly::messaging, wildfly::undertow, etc) were built for Wildfly 8.x and may not work with other versions. When there is a proven alternative for a different version, examples might be provided, otherwise you'll need to build your own abstraction using wildfly_resource or wildfly::resource.

One discussed approach would be to generate defined types based on Wildfly's configuration schemas ($WILDFLY_HOME/docs/schema) or DMR (See Issue 174).

JBoss EAP only works with RHEL-based OS's unless you provide custom scripts.

This bug might also be a problem for standalone-full-ha users of JBoss EAP < 7.

Development

Testing

This module uses puppet-lint, rubocop, rspec-puppet, beaker and travis-ci. We hope you use them before submitting your PR.

Hopefully, you'll need rvm to get the correct gems installed (and not messing with your computer's Ruby setup). Pls follow official installation instructions, plus:

sudo usermod -aG rvm $USER
echo 'source "/etc/profile.d/rvm.sh"' >> ~/.bashrc

Reboot for all changes to take effect, then install Ruby 2.7:

# Didn't work for installing Ruby 2.7, but looks wise:
rvm autolibs enable
# Ruby 2.7 dependency
rvm pkg install openssl
Beware, 'rvm pkg ...' is deprecated, read about the new autolibs feature: 'rvm help autolibs'.
# Inside this project's root directory:
rvm install ruby-2.7 --with-openssl-dir=/usr/share/rvm/usr
rvm use ruby-2.7
# Validate
ruby -v
ruby 2.7.x (20XX-YY-ZZ revision &lt;Hash&gt;) [x86_64-linux]
gem install bundler --no-document
bundle config set --local without 'development'
bundle install

bundle exec rake syntax
bundle exec rake lint
bundle exec rubocop
bundle exec rake spec

Acceptance tests (Beaker) can be executed using ./acceptance.sh. There is a 4x6 matrix (Wildfly 8/8.2/9/10 X Centos 6/7, Debian 7/8, Ubuntu 12.04/14.04).

I suggest you create a ~/.vagrant.d/Vagrantfile file and install vagrant-cachier plugin with the following content to speed up the execution:

Vagrant.configure(2) do |config|
  if Vagrant.has_plugin?('vagrant-cachier')
    config.cache.scope = :box
    config.cache.enable :yum
    config.cache.enable :apt
    config.cache.enable :generic, 'wget' => { cache_dir: '/var/cache/wget' }
  end
end

It takes ~3 minutes per test.

New features

JBoss/Wildfly configuration management is based on three custom types, wildfly_resource, wildfly_cli and wildfly_deployment. And you can do virtually any configuration that is possible through JBoss-CLI or XML configuration using them.

So, before build your awesome definition to manage a new resource or introduce a new configuration in an existing resource, check wildfly::* (wildfly::deployment, wildfly::datasources::*, wildfly::undertow::*, wildfly::messaging::*) for guidance.

If you can't figure out how to achieve your configuration, feel free to open an issue.

Author/Contributors

  • Edwin Biemond (biemond at gmail dot com)
  • Jairo Junior (junior.jairo1 at gmail dot com)
  • More

Documentation

see REFERENCE.md

Transfer Notice

This project was originally authored by biemond. The maintainer preferred that Vox Pupuli take ownership of the project for future improvement and maintenance. Existing pull requests and issues were transferred over, please fork and continue to contribute here instead of biemond-wildlfy.

puppet-wildfly's People

Contributors

admont avatar alexjfisher avatar bastelfreak avatar biemond avatar bjwschaap avatar blues-man avatar bobvanb avatar briehman avatar cinerama70 avatar emersonprado avatar ferrancg avatar icetrain avatar jairojunior avatar jeffmccune avatar jhazelwo avatar joris29 avatar kwolf avatar mikemarseglia avatar mpeter avatar mtdjr avatar raryates avatar rwaffen avatar smbambling avatar smortex avatar smunlimited avatar tstibbs avatar ubbo avatar will-wk-chan avatar zilchms avatar zipkid 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

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  avatar  avatar  avatar  avatar  avatar

puppet-wildfly's Issues

Update resources that depend on others fails

If you have a resource (e.g. a deployment) that depends on another resource (e.g. a datasource) and you try to update the datasource, it will fail cause wildfly_resource is not actually updating the resource, property by property, it's removing and inserting again.

Resource update should assemble a update-properties operation in order to avoid this issue.

Set JAVA_OPTS for Standalone

I need to add some java opts for wildfly for our ear. I'm working on this currently by converting the bin/standalone.conf file into an erb and puppeting it.

config file to listen on all interface [0.0.0.0]

I just used your module, thanks for making one.

What I noticed, that after installing wildfly listen on localhost i.e [127.0.0.1] rather then [0.0.0.0]
The config variable

class { '::wildfly' :
    version           => $version,
    install_source    => "http://download.jboss.org/wildfly/$version.Final/wildfly-$version.Final.tar.gz",
    java_home         => "/opt/jdk-$version",
    group             => 'wildfly',
    user              => 'wildfly',
    dirname           => "/opt/wildfly",
    mode              => "standalone",
    config            => "standalone-full.xml",
}

This is class which is calling a config variable

init.pp
  $config            = $wildfly::params::config, #jboss_config

Which goes to params.pp and has a value "standalone-full.xml"

params.pp
  $config            = 'standalone-full.xml'

This the one of exec which looks for "wildfly::config" which has value standalone-full.xml

exec { 'replace management bind':
    command => "sed -i -e's/jboss.bind.address.management:127.0.0.1/jboss.bind.address.management:${wildfly::mgmt_bind}/g' ${wildfly::dirname}/standalone/configuration/${wildfly::config}",
    path    => '/bin:/sbin:/usr/bin:/usr/sbin',
    onlyif  => "grep 'jboss.bind.address.management:127.0.0.1' ${wildfly::dirname}/standalone/configuration/${wildfly::config}",
  }

To me it looks like we are running sed on the wrong file here. or just i'm understanding the whole thing?

I manually edited the standalone.xml and changed localhost to [0.0.0.0] and it started listening on all the interface.

Invalid recursive parameter in wildfly resources

Setup is

  wildfly::config::add_app_user { 'Adding user':
    username => 'user',
    password => 'password'
  }

  wildfly::standalone::deploy { 'app.war': source => "file:///home/wildfly/app.war", 
  }

  wildfly::standalone::undertow::https { 'app':
    socket_binding    => 'https',
    keystore_path     => "${wildflyhome}/bin/server.store",
    keystore_password => 'password',
    key_alias         => "*.${::domain}",
    key_password      => 'password',
  }

This results in:

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Invalid parameter recursive on Wildfly_resource[/core-service=management/security-realm=TLSRealm] at /etc/puppet/environments/devtest/modules/wildfly/manifests/util/resource.pp:13 on node xxx.xxx.xxx
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

Simple fix was to remove line 11 in resource.pp (recursive => $recursive,)

Min/Max Pool size modified on every Puppet run adding "" around the values

I have a datasource resource that I am creating

wildfly::standalone::datasources::datasource { 'jpnDS':
    config => {
      'driver-name'    => 'mysql',
      'min-pool-size'  => '10',
      'max-pool-size'  => '60',
      'connection-url' => 'jdbc:mysql://localhost:3306/DB',
      'jndi-name'      => 'java:jboss/datasources/jpnDS',
      'user-name'      => 'my_app',
      'password'       => 'my_app'
    }
  }

It looks to correctly create the datasource but then on every run it tries to modify the resource to append quotes " around the values.

$ sudo puppet apply --modulepath=/vagrant/modules/ /vagrant/manifests/jboss_wildfly9.pp

Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Faraday: you may want to install system_timer for reliable timeouts
Notice: Compiled catalog for wildfly.example.dev in environment production in 1.22 seconds
Notice: /Stage[main]/Whois_wildfly/Wildfly::Standalone::Datasources::Datasource[jpnDS]/Wildfly::Util::Resource[/subsystem=datasources/data-source=jpnDS]/Wildfly_resource[/subsystem=datasources/data-source=jpnDS]/state: state changed '{"max-pool-size"=>60, "min-pool-size"=>10}' to '{"max-pool-size"=>"60", "min-pool-size"=>"10"}'
Notice: Finished catalog run in 1.13 seconds

Support XA Datasources

I need to add an XA datasource to Wildfly. After a lot of trial and error I've been able to add an XA datasource via the management API using this request.

{
    "operation": "composite",
    "address": [],
    "steps": [
        {
            "address": [
                {
                    "subsystem": "datasources"
                },
                {
                    "xa-data-source": "DefaultPool"
                }
            ],
            "driver-name": "oracle",
            "jndi-name": "java:/jdbc/DefaultPool",
            "operation": "add",
            "password": "password",
            "user-name": "undef"
        }, {
            "address": [
                {
                    "subsystem": "datasources"
                },
                {
                    "xa-data-source": "DefaultPool"
                },
                {
                    "xa-datasource-properties": "URL"
                }
            ],
            "operation": "add"
        }
    ]
}

The second step is needed in the same request otherwise the request fails for not having any xa-datasource-properties. I've been trying to figure out the best way to work this into the code base, but I'm not seeing any straightforward ways. Any suggestions on how to achieve this in a way that's merge worthy?

Update: realized the first step had still had a xa-datasource-property field that did nothing from my testing. Removed it.

osfamily keys have to be a strings?

I had to change in manifests/params.pp line 10:

$service_file  = $::osfamily? {
    Debian => 'wildfly-init-debian.sh',
    RedHat  => 'wildfly-init-redhat.sh',
    default => 'wildfly-init-redhat.sh',
}

to

$service_file  = $::osfamily? {
    'Debian' => 'wildfly-init-debian.sh',
    'RedHat'  => 'wildfly-init-redhat.sh',
    default => 'wildfly-init-redhat.sh',
}

I am not sure if it has something to do with the puppet version I use (3.7.4). And I have not tested RedHat an default, so i did not want to open a pull request as I am not sure about this change.

CLI tries to use proxy in PE4

When using PE4, which uses Ruby 2, Net::HTTP honours the http_proxy environment variable. PE<4 doesn't have this behaviour since in Ruby 1.x the Net::HTTP ignores http_proxy. I think wildfly_cli.rb should be modified to explicitly pass nil as proxy host to ignore the proxy, because the API connection will always be local (or should be).

init.d script for wildfly versions prior to 8.2.0 doesn't recognize variable JBOSS_OPTS

Since @jairojunior closed the issue #68, the wildfly module allowed wildfly::public_bind and wildfly::mgmt_bind to set bind address value by informing a value to JBOSS_OPTS variable, which is read by the jboss-as-{domain,standalone}.sh scripts.

The variable JBOSS_OPTS is completed ignored in the init.d scripts of wildfly versions prior to 8.2.0, such as 8.1.0, 8.0.0 and all EAP 6.x versions, therefore setting the variables wildfly::public_bind and wildfly::mgmt_bind on the puppet module doesn't change bind address configuration. Other settings that depend on JBOSS_OPTS won't work, also.

Supports file protocol in wildfly::deployment and wildfly::module

Since archive was replaced by execs, only http:// and ftp:// protocol are supported. In order to fully support external archive modules[1], file:// support must be implemented.

[1]

archive::nexus { '/tmp/hawtio.war':
  ensure        => present,
  url               => $nexus_url,
  gav             => "'io.hawt:hawtio-web:1.4.59'",
  packaging  => 'war',
  repository   => $repository,
  owner         => 'wildfly',
  group         => 'wildly',
}
~>
wildfly::deployment { 'hawtio.war':
  source => 'file:/tmp/hawtio.war',
}

wildfly_deploy fails when deploying in standalone mode.

Upgraded the module from 0.3.5 to 0.4.0. Adjusted the classes appropriately, as per the CHANGELOG.

  ::wildfly::deploy { 'foo.war':
    source  => "${prefix}/${groupid_path}/foo/${version}/foo-${version}.war",
    require => Service['jboss'],
  }

Receives an error:

Invalid parameter server_group on Wildfly_deploy[foo.war] at /etc/puppet/environments/<branch>/modules/wildfly/manifests/deploy.pp:69

It looks like server_group is required, which I believe won't work correctly when deploying in standalone mode.

Deploy in Domain mode

Can you make a feature that deploy, assign and enable application on separate servers in server-group in "domain" mode?

when standalone.xml is modified outside of puppet wildfly fails

I deploy an app to the server using an install script. The install script copies over or modifies /opt/wildfly/standalone/configuration/standalone.xml.

standalone.xml is then "fixed" by a subsequent puppet run, after the application install script. See augeas output below.

Notice: Augeas[public](provider=augeas):
--- /opt/wildfly/standalone/configuration/standalone.xml    2015-10-08 22:17:50.740310945 -0400
+++ /opt/wildfly/standalone/configuration/standalone.xml.augnew 2015-10-08 22:22:24.114023287 -0400
@@ -488,7 +488,7 @@
             <inet-address value="${management.interface.ip}"/>
         </interface>
         <interface name="public">
-            <inet-address value="${public.interface.ip}"/>
+            <inet-address value="${jboss.bind.address:0.0.0.0}"/>
         </interface>
         <interface name="unsecure">
             <inet-address value="${unsecure.interface.ip}"/>

Notice: /Stage[main]/Wildfly::Setup/Wildfly::Config::Interfaces[public]/Augeas[public]/returns: executed successfully
Notice: Augeas[management](provider=augeas):
--- /opt/wildfly/standalone/configuration/standalone.xml    2015-10-08 22:22:24.265026992 -0400
+++ /opt/wildfly/standalone/configuration/standalone.xml.augnew 2015-10-08 22:22:24.348029029 -0400
@@ -485,7 +485,7 @@

     <interfaces>
         <interface name="management">
-            <inet-address value="${management.interface.ip}"/>
+            <inet-address value="${jboss.bind.address.management:0.0.0.0}"/>
         </interface>
         <interface name="public">
             <inet-address value="${jboss.bind.address:0.0.0.0}"/>

Notice: /Stage[main]/Wildfly::Setup/Wildfly::Config::Interfaces[management]/Augeas[management]/returns: executed successfully
Notice: Augeas[http](provider=augeas):
--- /opt/wildfly/standalone/configuration/standalone.xml    2015-10-08 22:22:24.500032756 -0400
+++ /opt/wildfly/standalone/configuration/standalone.xml.augnew 2015-10-08 22:22:24.663036755 -0400
@@ -499,7 +499,7 @@
         <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
         <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
         <socket-binding name="ajp" port="${ajp.connector.port}"/>
-        <socket-binding name="http" port="${http.connector.port}"/>
+        <socket-binding name="http" port="${jboss.http.port:8080}"/>
         <socket-binding name="jgroups-tcp" port="${jgroups.tcp.port}"/>
         <socket-binding name="jgroups-tcp-fd" port="${jgroups.tcp.fd.port}"/>
         <socket-binding name="https" port="8443"/>

Notice: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[http]/Augeas[http]/returns: executed successfully
Notice: Augeas[https](provider=augeas):
--- /opt/wildfly/standalone/configuration/standalone.xml    2015-10-08 22:22:24.825040730 -0400
+++ /opt/wildfly/standalone/configuration/standalone.xml.augnew 2015-10-08 22:22:24.908042766 -0400
@@ -502,7 +502,7 @@
         <socket-binding name="http" port="${jboss.http.port:8080}"/>
         <socket-binding name="jgroups-tcp" port="${jgroups.tcp.port}"/>
         <socket-binding name="jgroups-tcp-fd" port="${jgroups.tcp.fd.port}"/>
-        <socket-binding name="https" port="8443"/>
+        <socket-binding name="https" port="${jboss.https.port:8443}"/>
         <socket-binding name="txn-recovery-environment" port="4712"/>
         <socket-binding name="txn-status-manager" port="4713"/>
         <outbound-socket-binding name="primary-mail-smtp">

Notice: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[https]/Augeas[https]/returns: executed successfully
Notice: Augeas[ajp](provider=augeas):
--- /opt/wildfly/standalone/configuration/standalone.xml    2015-10-08 22:22:25.058046447 -0400
+++ /opt/wildfly/standalone/configuration/standalone.xml.augnew 2015-10-08 22:22:25.141048483 -0400
@@ -498,7 +498,7 @@
     <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
         <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
         <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
-        <socket-binding name="ajp" port="${ajp.connector.port}"/>
+        <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
         <socket-binding name="http" port="${jboss.http.port:8080}"/>
         <socket-binding name="jgroups-tcp" port="${jgroups.tcp.port}"/>
         <socket-binding name="jgroups-tcp-fd" port="${jgroups.tcp.fd.port}"/>

Notice: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[ajp]/Augeas[ajp]/returns: executed successfully
Notice: /Stage[main]/Profiles::Appserver/Wildfly::Datasources::Driver[Driver mysql]/Wildfly::Util::Resource[/subsystem=datasources/jdbc-driver=mysql]/Wildfly_resource[/subsystem=datasources/jdbc-driver=mysql]/state: state changed '{"driver-xa-datasource-class-name"=>nil}' to '{"driver-xa-datasource-class-name"=>"undef"}'

Notice: Finished catalog run in 15.06 seconds

wildfly service is then failed, returning '404'.

if i restart wildfly then the app starts working again.

I think there needs to be a refresh on the wildfly service if standalone.xml is ever modified. I checked a couple manifests in config and it appears none of the augeas resources notify the wildfly service.

perhaps a notify would fix this issue? from manifests/config/socket_binding.pp

  augeas { $name:
    lens    => 'Xml.lns',
    incl    => "${wildfly::dirname}/${wildfly::mode}/configuration/${wildfly::config}",
    changes => "set server/socket-binding-group/socket-binding[#attribute/name='${name}']/#attribute/port ${port}",
    onlyif  => "match server/socket-binding-group/socket-binding[#attribute/name='${name}'][#attribute/port='${port}'] size == 0",
    notify => Service['wildfly'],
  }

does that seem appropriate?

Split module into wildfly (install, config & service) and wildfly_admin (management)

I've been thinking about break the module into two modules:

  • One for wildfly installation
  • One for wildfly administration

My point is that administration/management is common across many JBoss AS (7+)/JBoss EAP(6+)/Wildfly(8+) versions, but installation and defines built on top of administration custom types/providers varies from one version to another.

Error: Could not run: cannot load such file -- faraday_middleware

Hi, I'm getting this error below, do you know why?

Error: /Stage[main]/Wildfly::Install/Archive[/tmp/wildfly-8.2.0.Final.tar.gz]/ensure: change from absent to present failed: cannot load such file -- faraday_middleware

...

Error: Could not run: cannot load such file -- faraday_middleware


My setup: centos 6.5, ruby-gems 1.8.3, puppet 4

This what I'm doing:

class { 'wildfly':
version => '8.2.0',
java_home => '/usr/lib/jvm/java-1.8.0-openjdk',
install_source => 'http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.tar.gz',
group => 'wildfly',
user => 'wildfly',
dirname => '/opt/wildfly',
mode => 'standalone',
config => 'standalone.xml',
java_xmx => '512m',
java_xms => '256m',
java_maxpermsize => '256m',
users_mgmt => { 'wildfly' => { username => 'wildfly', password => 'wildfly'}},
}

Issue creating periodic-rotating-file-handler with Wildly_resource type

I've hit an issue when trying to use the wildfly_resource type to create a periodic-rotating-file-handler with the name WHOIS-PROXY-QUERY-FILE.

When running Puppet apply I get the following error

$ sudo puppet apply --modulepath=/vagrant/modules /vagrant/manifests/jboss_wildfly8.pp
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Faraday: you may want to install system_timer for reliable timeouts
Notice: Compiled catalog for wildfly.example.dev in environment production in 1.14 seconds
Error: /Stage[main]/Main/Wildfly_resource[/subsystem=logging/periodic-rotating-file-handler=WHOIS-PROXY-QUERY-FILE]: Could not evaluate: private method `gsub' called for nil:NilClass
Notice: Finished catalog run in 0.76 seconds

If the name is modified it works without issue. I'm not sure what is tripping to make it error.

$ sudo puppet apply --modulepath=/vagrant/modules /vagrant/manifests/jboss_wildfly8.pp
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Faraday: you may want to install system_timer for reliable timeouts
Notice: Compiled catalog for wildfly.example.dev in environment production in 1.06 seconds
Notice: /Stage[main]/Main/Wildfly_resource[/subsystem=logging/periodic-rotating-file-handler=WHOIS-PROXY-FILE]/ensure: created
Notice: Finished catalog run in 0.71 seconds

puppet agent fails to run ` Could not autoload puppet/type/wildfly_resource`

What is happening sometime puppet fails to run and sometime it does not fail. I don't think the require statement under http_api file, would be creating any problem. any idea why this sudden burst of puppet

puppet agent t --environment=ashish
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not autoload puppet/type/wildfly_resource: Could not autoload puppet/provider/wildfly_resource/http_api: no such file to load - puppet_x/util/wildfly_cli on node beaker-role-appeng-wildfly-centos7-menywugg.ashish
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

Conflicts on the archive module

I'm not sure if there's a good way to resolve this (or if this is an issue I should bring up here), but I've run into a conflict with other modules' dependency on camptocamp's archive and this module's usage of nanliu's archive. I've done some work to switch to camptocamp in a fork, but I'm curious if it would be a good idea to optionally split out the usage of archive in this module. I'd rather avoid having to rely on a fork in the long run, but it seems module namespacing conflicts is one of puppet's weak points.

Deployment via nexus fails.

Deployment using nexus does not work. There is no support for nexus in nanliu/arhive and in deploy.pp line 21 "archive::nexus" fails.

bad default config file name

the line
file{'/etc/default/wildfly.conf':
should be
file{'/etc/default/wildfly':
the service script is looking for the later file name.

BTW: there should be java dependency added.

Add `login-module` resource type

I've implemented the wildfly::security::domain with support for just one login-module. However, security domains can have multiple login-modules, and maybe log-modules should/could be managed independently of the security domain.

I've refactored wildfly::security::domain to do a create_resources of wildfly::security::login_module and added the wildfly::security::login_module resource itself.

Pull-request will follow..

Error when WARs take a 'long' time to deploy

I have some WARs that take a while to complete the deploy process ( lot of DB hibernate checks ).

Error: Could not set 'present' on ensure: Net::ReadTimeout at 61:/vagrant/modules/wildfly/manifests/deploy.pp
Error: Could not set 'present' on ensure: Net::ReadTimeout at 61:/vagrant/modules/wildfly/manifests/deploy.pp Wrapped exception:Net::ReadTimeout
Error:/Stage[main]/Rdap_bootstrap_server::Deploy/Wildfly::Deploy[rdap_bootstrap_server.war]/Wildfly_deploy[rdap_bootstrap_server.war]/ensure: change from absent to present failed: Could not set 'present' on ensure: Net::ReadTimeout at 61:/vagrant/modules/wildfly/manifests/deploy.pp

Add parameters for controlling wildfly service

Sometimes it is necessary to be able to control the state of the service outside of Puppet. For that reason I'd like to add some parameters to specify the behaviour of the wildfly service:

  • service_ensure; be able to optionally set ensure to present instead of running (default)
  • service_enable; be able to optionally make wildfly not start at system boot
  • custom_init; provide a custom template for the init.d script from e.g. a wrapper module

I use this to provide a custom startup script that has a 'defer' function which allows us to temporarily stop de service during e.g. a test or maintenance window without Puppet trying to start it during its run.

I think this would make the module more 'batteries included but removable' ;-)

I will provide a pull request for this.

always `state changed` for recursive `wildfly::util::resource`

I have a recursive resource. E.g. (partial example):

wildfly::util::resource { "/core-service=management/security-realm=${realm_name}/authorization=ldap":
    recursive => true,
    content   => {
      'connection' => "${realm_name}-LDAPConnection",
      'group-search' => {
        'group-to-principal' => {
          'group-name'                 => $authorization_group_name,
          'group-name-attribute'       => $authorization_group_name_attribute,
          'group-dn-attribute'         => $authorization_group_dn_attribute,
          'base-dn'                    => $authorization_group_base_dn,
          'search-by'                  => $authorization_group_search_by,
          'principal-attribute'        => $authorization_principal_attribute,
          'recursive'                  => $authorization_group_recursive,
          'iterative'                  => $authorization_group_iterative,
          'prefer-original-connection' => $authorization_prefer_original_conn,
          'cache' => {
            "${cache_type}" => {
              'max-cache-size' => $max_cache_size,
              'eviction-time'  => $cache_eviction_time,
              'cache-failures' => $cache_failures,
            }
          }
      }},
      'username-to-dn' => {
        'username-filter' => {
          'base-dn'           => $ldap_user_base_dn,
          'attribute'         => $authorization_user_name_attribute,
          'user-dn-attribute' => $authorization_user_dn_attribute,
          'force'             => $authorization_user_force,
          'recursive'         => $authorization_user_recursive,
          'cache' => {
            "${cache_type}" => {
              'max-cache-size' => $max_cache_size,
              'eviction-time'  => $cache_eviction_time,
              'cache-failures' => $cache_failures,
            }
          }
      }},
    },
  }

Each Puppet run will cause a state changed because Puppet thinks the resources are dissimilar. This is incorrect since the resources are similar.

Module is one version behind with 8.2.0 released now

I'm working to deploy Wildfly 8.2.0 and so far have simply changed version = 8.2.0 in order to deploy it. This appears to work so far, but it would be nice to see this become the new default.

I'm happy to help test it with 8.2.0 if you have a testing routine or suggestions as to what I should run against my install to test it.

XA Datasource always updates

Seems I didn't test recursive resources enough. My XA Datasource resource always updates even when it shouldn't. I plan on taking a look at this sometime this week.

Set Exec download timeout parametric

Hi,
I'm using this module also to deploy also Keycloak, just changing $version and $install_source, and everything is fine but it happens that sometimes download is slower thus Exec timeout expires.

A possibile workaround now could be:

Exec["Download wildfly from ${install_source}"] { timeout => 1000 }

instead of setting global Exec timeout or modify wildfly module.

Maybe a $install_source_timeout in wildfly class constructor could help

Add support for setting driver-class-name property on datasource driver

Right now the module only supports the driver-xa-datasource-class-name property on a JDBC driver. However, when using a non-XA driver, the driver-class-name property could be more appropriate.

A direction might be to add a driver_class_name parameter to wildfly::datasources::driver, differentiate between a XA and non-XA driver, or make wildfly::datasources::driver 'transparent' by using e.g. a hash instead of named parameters/arguments.

"domain" mode

what's wrong with domain mode?

if i set this:
class {'::wildfly':
version => '8.2.0', install_source => 'http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.tar.gz', java_home => '/opt/jdk1.7.0_79', group => 'wildfly', user => 'wildfly', dirname => '/opt/wildfly',
mode => 'domain',
config => 'domain.xml',
java_xmx => '512m', java_xms => '256m', java_maxpermsize => '256m', users_mgmt => { 'wildfly' => { username => 'admin', password => '1'}},
}

i get that:

==> web1: Notice: /Stage[main]/Wildfly::Install/Archive[/tmp/wildfly-8.2.0.Final.tar.gz]/ensure: download archive from http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.tar.gz to /tmp/wildfly-8.2.0.Final.tar.gz and extracted in /opt/wildfly with cleanup
==> web1: Error: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[ajp]/Augeas[ajp]: Could not evaluate: Save failed with return code false, see debug
==> web1: Notice: /Stage[main]/Wildfly::Setup/Exec[replace memory parameters]/returns: executed successfully
==> web1: Error: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[management-http]/Augeas[management-http]: Could not evaluate: Save failed with return code false, see debug
==> web1: Error: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[management-https]/Augeas[management-https]: Could not evaluate: Save failed with return code false, see debug
==> web1: Error: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[http]/Augeas[http]: Could not evaluate: Save failed with return code false, see debug
==> web1: Error: /Stage[main]/Wildfly::Setup/Wildfly::Config::Interfaces[public]/Augeas[public]: Could not evaluate: Save failed with return code false, see debug
==> web1: Error: /Stage[main]/Wildfly::Setup/Wildfly::Config::Interfaces[management]/Augeas[management]: Could not evaluate: Save failed with return code false, see debug
==> web1: Notice: /Stage[main]/Wildfly::Setup/Wildfly::Config::Add_mgmt_user[wildfly]/Wildfly::Config::Add_user[wildfly]/File_line[admin:ManagementRealm]/ensure: created
==> web1: Notice: /Stage[main]/Profile::Maven/Exec[export MVN_PATH]/returns: executed successfully
==> web1: Error: /Stage[main]/Wildfly::Setup/Wildfly::Config::Socket_binding[https]/Augeas[https]: Could not evaluate: Save failed with return code false, see debug

wget breaks wildfly::config::module

The new wget functionality breaks the module, since it behaves differently from the previously used archive and curl functionality:

wget -N -P ${dir_path}/${file_name} ${source} --max-redirect=5

causes wget to create a subdirectory with the name ${file_name} to be created, and the downloaded file will be placed in there. This causes classloading errors since Wildfly won't be able to find the jar in the 'current' directory. E.g.: when creating a PostgreSQL module the resulting file resource is:

$WILDFLY_HOME/modules/system/layers/base/org/postgresql/main/postgresql-9.4-1204.jdbc41.jar/postgresql-9.4-1204.jdbc41.jar

while it should be:

$WILDFLY_HOME/modules/system/layers/base/org/postgresql/main/postgresql-9.4-1204.jdbc41.jar

I will provide a pull request with a fix.

Management interface does not always use Digest authentication

Right now wildfly::util::resource items are created using direct interaction with the http management API using the wildfly_cli.rb code. This code makes an invalid assumption that authentication to the management API always uses Digest.

However, I observed that when configuring your own security realm with LDAP, and attaching it to the http management interface, the authentication method can differ. E.g. with the authentication=ldap setting, authentication on the http management interface uses Basic auth (!).

It was my invalid assumption that Wildfly would handle http authentication, and only delegate the validation of the credentials to the methods defined by the security realm. This is not true, as the entire http request seems to be forwarded. So the http authentication used, depends on the configuration of the security realm.

I will provide a pull request that makes wildfly_cli.rb detect which authentication method to use, and switch between Digest or Basic accordingly.

Datasource always change state, if there is a number in it.

I've made a wildfly datasource, where some config keys have number in.
'min-pool-size' => 1,
'max-pool-size' => 10,
It configure it right, but every puppet run it tells me that state changed.
/state: state changed '{"max-pool-size"=>10, "min-pool-size"=>1}' to '{"min-pool-size"=>"1", "max-pool-size"=>"10"}'

Connection refused after reload is issued via Wildfly::Util::Exec_cli

I have a profile manifest where I am removing subsystem=ee/service=default-bindings] which requires a reload. I'm using the Wildfly::Util::Exec_cli call to issue a reload which works correctly.

The issues is that tasks that are run directly after that reload fail because the management interface is temporarily unavailable after the reload.

Error: /Stage[main]/Jolokia::Deploy/Wildfly::Deploy[jolokia war]/Wildfly_deploy[jolokia war]: Could not evaluate: Connection refused - connect(2) for "0.0.0.0" port 9990

Is there an suggestions for making the reload not report completed to puppet unless it can access the management interface to stop additional tasks from failing ?

Centos7 wildfly service fails for the first time

Puppet runs fails for the first time on centos

Notice: /Stage[main]/Apache::Service/Service[httpd]: Triggered 'refresh' from 1 events
Error: Could not start Service[wildfly]: Execution of '/bin/systemctl start wildfly' returned 6: Failed to start wildfly.service: Unit wildfly.service failed to load: No such file or directory.
Error: /Stage[main]/Wildfly::Service/Service[wildfly]/ensure: change from stopped to running failed: Could not start Service[wildfly]: Execution of '/bin/systemctl start wildfly' returned 6: Failed to start wildfly.service: Unit wildfly.service failed to load: No such file or directory.

Manually starting wildly

[root@beaker-role-appeng-wildfly-centos7-mrfkyciu ~]# service wildfly start
Reloading systemd:  Error getting authority: Error initializing authority: Could not connect: Connection refused (g-io-error-quark, 39)
                                                           [  OK  ]
Starting wildfly (via systemctl):  Error getting authority: Error initializing authority: Could not connect: Connection refused (g-io-error-quark, 39)
                                                           [  OK  ]

And then it works proper,

  1. First I check the status with systemctl command and it reports perfectly fine
  2. Then I stop the wildly with systemctl and works properly.
  3. Then starting the wildly with systemctl works properly.

Looks like first time we have to start the service with manually.

[root@beaker-role-appeng-wildfly-centos7-mrfkyciu ~]# systemctl status wildfly
● wildfly.service - SYSV: WildFly startup script
   Loaded: loaded (/etc/rc.d/init.d/wildfly)
   Active: active (running) since Wed 2015-12-30 03:59:19 UTC; 5s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 4473 ExecStart=/etc/rc.d/init.d/wildfly start (code=exited, status=0/SUCCESS)
 Main PID: 4576 (java)
   CGroup: /lxc/beaker/lxc/beaker-role-appeng-wildfly-centos7-mrfkyciu/system.slice/wildfly.service
           ├─4481 /bin/sh /etc/rc.d/init.d/wildfly start
           ├─4484 runuser -s /bin/bash wildfly -c ulimit -S -c 0 >/dev/null 2>&1 ; LAUNCH_JBOSS_IN_BACKGROUND=1 JBOSS_PIDFILE=/var/run/wildfly/wildfly.pid ...
           ├─4485 bash -c ulimit -S -c 0 >/dev/null 2>&1 ; LAUNCH_JBOSS_IN_BACKGROUND=1 JBOSS_PIDFILE=/var/run/wildfly/wildfly.pid /opt/wildfly/bin/standal...
           ├─4486 /bin/sh /opt/wildfly/bin/standalone.sh -c standalone-full.xml -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0 -Djbos...
           └─4576 java -D[Standalone] -server -XX:+UseCompressedOops -server -XX:+UseCompressedOops -Xms256m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.boot...

Dec 30 03:59:03 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Starting SYSV: WildFly startup script...
Dec 30 03:59:19 beaker-role-appeng-wildfly-centos7-mrfkyciu wildfly[4473]: Starting wildfly: [  OK  ]
Dec 30 03:59:19 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: wildfly.service: Supervising process 4576 which is not our child. We'll most ...exits.
Dec 30 03:59:19 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Started SYSV: WildFly startup script.
Hint: Some lines were ellipsized, use -l to show in full.
[root@beaker-role-appeng-wildfly-centos7-mrfkyciu ~]# systemctl stop wildfly
Error getting authority: Error initializing authority: Could not connect: Connection refused (g-io-error-quark, 39)
[root@beaker-role-appeng-wildfly-centos7-mrfkyciu ~]# systemctl status wildfly
● wildfly.service - SYSV: WildFly startup script
   Loaded: loaded (/etc/rc.d/init.d/wildfly)
   Active: inactive (dead)
     Docs: man:systemd-sysv-generator(8)

Dec 30 03:59:03 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Starting SYSV: WildFly startup script...
Dec 30 03:59:19 beaker-role-appeng-wildfly-centos7-mrfkyciu wildfly[4473]: Starting wildfly: [  OK  ]
Dec 30 03:59:19 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: wildfly.service: Supervising process 4576 which is not our child. We'll most ...exits.
Dec 30 03:59:19 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Started SYSV: WildFly startup script.
Dec 30 03:59:31 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Stopping SYSV: WildFly startup script...
Dec 30 03:59:32 beaker-role-appeng-wildfly-centos7-mrfkyciu wildfly[4745]: Stopping wildfly: [  OK  ]
Dec 30 03:59:32 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Stopped SYSV: WildFly startup script.
Hint: Some lines were ellipsized, use -l to show in full.
[root@beaker-role-appeng-wildfly-centos7-mrfkyciu ~]# systemctl start wildfly
Error getting authority: Error initializing authority: Could not connect: Connection refused (g-io-error-quark, 39)
[root@beaker-role-appeng-wildfly-centos7-mrfkyciu ~]# systemctl status wildfly
● wildfly.service - SYSV: WildFly startup script
   Loaded: loaded (/etc/rc.d/init.d/wildfly)
   Active: active (running) since Wed 2015-12-30 03:59:55 UTC; 1s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 4786 ExecStart=/etc/rc.d/init.d/wildfly start (code=exited, status=0/SUCCESS)
 Main PID: 4889 (java)
   CGroup: /lxc/beaker/lxc/beaker-role-appeng-wildfly-centos7-mrfkyciu/system.slice/wildfly.service
           ├─4794 /bin/sh /etc/rc.d/init.d/wildfly start
           ├─4797 runuser -s /bin/bash wildfly -c ulimit -S -c 0 >/dev/null 2>&1 ; LAUNCH_JBOSS_IN_BACKGROUND=1 JBOSS_PIDFILE=/var/run/wildfly/wildfly.pid ...
           ├─4798 bash -c ulimit -S -c 0 >/dev/null 2>&1 ; LAUNCH_JBOSS_IN_BACKGROUND=1 JBOSS_PIDFILE=/var/run/wildfly/wildfly.pid /opt/wildfly/bin/standal...
           ├─4799 /bin/sh /opt/wildfly/bin/standalone.sh -c standalone-full.xml -Djboss.bind.address=0.0.0.0 -Djboss.bind.address.management=0.0.0.0 -Djbos...
           └─4889 java -D[Standalone] -server -XX:+UseCompressedOops -server -XX:+UseCompressedOops -Xms256m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.boot...

Dec 30 03:59:39 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Starting SYSV: WildFly startup script...
Dec 30 03:59:55 beaker-role-appeng-wildfly-centos7-mrfkyciu wildfly[4786]: Starting wildfly: [  OK  ]
Dec 30 03:59:55 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: wildfly.service: Supervising process 4889 which is not our child. We'll most ...exits.
Dec 30 03:59:55 beaker-role-appeng-wildfly-centos7-mrfkyciu systemd[1]: Started SYSV: WildFly startup script.
Hint: Some lines were ellipsized, use -l to show in full.```

Add support for operation headers

The HTTP management API has so-called operation-headers, which allow some resources to be added without requiring the (full) server to reload. Please see:
https://docs.jboss.org/author/display/WFLY9/Management+API+reference#ManagementAPIreference-OperationHeaders
I think we should offer support for these headers, so that some resources can be added more efficiently because then they won't require the server to reload.
Looking at the code I think this feature could actually be implemented easily and quickly..

How to remove a datasource resource

How would you go about removing a resource only if it exists with the custom types ?

My attempt to use the following removes the resource....

wildfly::util::exec_cli { "Disable ExampleDS":
  command => "/subsystem=datasources/data-source=ExampleDS:remove",
  unless  => "(outcome == failed) of /subsystem=datasources/data-source=ExampleDS:read-resource"
}

...but once removed the next run of puppet fails

Error: /Stage[main]/Main/Wildfly::Util::Exec_cli[Disable ExampleDS]/Wildfly_cli[Disable ExampleDS]: Could not evaluate: Failed with: JBAS014807: Management resource '[
    ("subsystem" => "datasources"),
    ("data-source" => "ExampleDS")
]' not found for {"address":[{"subsystem":"datasources"},{"data-source":"ExampleDS"}],"operation":"read-resource"}

Update of mgmt.properties requires a complete installation of WildFly

In the file manifests/install.pp:
{code}
file{"${dirname}/standalone/configuration/mgmt-users.properties":
ensure => present,
mode => '0755',
owner => $user,
group => $group,
content => template('wildfly/mgmt-users.properties.erb'),
before => Service['wildfly'],
}
{code}

To fix this issue add:
{code}
require => Exec["tar ${install_file} in /var/tmp"],
{code}

Travis build fails

Submitting to Coveralls fails with:
{"message":"Couldn't find a repository matching this job.","error":true}

Improve domain support

Domain support is still tied to augeas, hence it only works on Wildfly versions < 9.0. Its support should be improved to use CLI-like resources and to provide built-in abstractions for servers and server-groups.

Package[faraday]: Provider gem is not functional on this host

Does this look familiar?
Info: Applying configuration version '1446849940'
Error: /Stage[main]/Archive/Package[faraday]: Provider gem is not functional on this host
Error: /Stage[main]/Archive/Package[faraday_middleware]: Provider gem is not functional on this host
Notice: /Stage[main]/Wildfly::Prepare/Group[wildfly]: Dependency Package[faraday] has failures: true
Notice: /Stage[main]/Wildfly::Prepare/Group[wildfly]: Dependency Package[faraday_middleware] has failures: true
Warning: /Stage[main]/Wildfly::Prepare/Group[wildfly]: Skipping because of failed dependencies

[root@puppetmaster modules]# puppet module install biemond-wildfly
Notice: Preparing to install into /etc/puppetlabs/code/environments/production/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Notice: Installing -- do not interrupt ...
/etc/puppetlabs/code/environments/production/modules
└─┬ biemond-wildfly (v0.4.3)
├─┬ nanliu-archive (v0.3.0)
│ └── puppetlabs-pe_gem (v0.1.1)
└── puppetlabs-stdlib (v4.9.0)
[root@puppetmaster modules]# puppet --version
4.2.2
[root@puppetmaster modules]#

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.