GithubHelp home page GithubHelp logo

voxpupuli / puppet-mcollective Goto Github PK

View Code? Open in Web Editor NEW
120.0 114.0 178.0 803 KB

MCollective Server and Client Puppet Module

Home Page: https://forge.puppet.com/puppet/mcollective

License: Apache License 2.0

Ruby 56.79% Puppet 36.62% HTML 5.63% PLSQL 0.60% Dockerfile 0.36%
linux-puppet-module puppet hacktoberfest centos-puppet-module debian-puppet-module oraclelinux-puppet-module redhat-puppet-module scientific-puppet-module sles-puppet-module ubuntu-puppet-module

puppet-mcollective's Introduction

MCollective module for Puppet

Build Status Code Coverage Puppet Forge Puppet Forge - downloads Puppet Forge - endorsement Puppet Forge - scores

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 mcollective
  4. Usage - Configuration options and additional functionality
  5. Reference - An under-the-hood peek at what the module is doing and how
  6. Limitations - OS compatibility, etc.
  7. Development - Guide for contributing to the module

Overview

The mcollective module installs, configures, and manages the mcollective agents, and clients of an MCollective cluster.

Module Description

The mcollective module handles installing and configuring mcollective across a range of operating systems and distributions. Where possible we follow the standards laid down by the MCollective Standard Deployment guide.

MCollective Terminology

A quick aside, mcollective's terminology differs a little from what you might be used to in puppet. There are 3 main components, the client (the mco commands you run to control your servers), the server (a daemon that runs on all of your managed nodes and executes the commands), and the middleware (a message broker the servers and agent connect to).

If it helps to map these to puppet concepts you loosely have:

  • Middleware -> Puppet Master
  • MCollective Server -> Puppet Agent
  • MCollective Client -> no direct equivalent

Setup

What the mcollective module affects

On a server

  • mcollective package
  • mcollective server configuration file
  • mcollective service

On a client

  • mcollective-client package
  • mcollective client configuration file
  • optionally user configuration files (~/.mcollective and ~/.mcollective.d)

Beginning with mcollective

Your main entrypoint to the mcollective module is the mcollective class, so assuming you have your middleware configured on a node this is all you need to add a server to mcollective.

class { '::mcollective':
  middleware_hosts => [ 'broker1.example.com' ],
}

Usage

Your primary interaction with the mcollective module will be though the main mcollective class, with secondary configuration managed by the defined types mcollective::user, mcollective::plugin, mcollective::actionpolicy, and mcollective::actionpolicy::rule.

I just want to run it, what's the minimum I need?

node 'broker1.example.com' {
  include activemq
}

node 'server1.example.com' {
  class { '::mcollective':
    middleware_hosts => [ 'broker1.example.com' ],
  }
}

node 'control1.example.com' {
  class { '::mcollective':
    client            => true,
    middleware_hosts => [ 'broker1.example.com' ],
  }
}

This default install will be using no TLS, a set of well-known usernames and passwords, and the psk securityprovider. This is against the recommendataion of the standard deploy guide but does save you from having to deal with ssl certificates to begin with.

I'd like to secure the transport channel and authenticate users, how do I do that?

Gather some credentials for the server and users. You'll need the ca certificate, and a keypair for the server to use, and a keypair for each user to allow.

See the standard deploy guide for more information about how to generate these.

node 'broker1.example.com' {
  # Please see
  # https://github.com/voxpupuli/puppet-mcollective/blob/master/examples/ssl_example/mco_profile/manifests/middleware/activemq.pp
  # for this as setting up activemq with a truststore can be quite complex.
}

node 'server1.example.com' {
  class { '::mcollective':
    middleware_hosts    => [ 'broker1.example.com' ],
    middleware_ssl      => true,
    middleware_ssl_cert => "/var/lib/puppet/ssl/certs/${::clientcert}.pem",
    middleware_ssl_key  => "/var/lib/puppet/ssl/private_keys/${::clientcert}.pem",
    middleware_ssl_ca   => "/var/lib/puppet/ssl/certs/ca.pem",
    securityprovider    => 'ssl',
    ssl_client_certs    => 'puppet:///modules/site_mcollective/client_certs',
    ssl_ca_cert         => 'puppet:///modules/site_mcollective/certs/ca.pem',
    ssl_server_public   => 'puppet:///modules/site_mcollective/certs/server.pem',
    ssl_server_private  => 'puppet:///modules/site_mcollective/private_keys/server.pem',
  }

  mcollective::actionpolicy { 'nrpe':
    default => 'deny',
  }

  mcollective::actionpolicy::rule { 'vagrant user can use nrpe agent':
    agent    => 'nrpe',
    callerid => 'cert=vagrant',
  }
}

node 'control.example.com' {
  class { '::mcollective':
    client              => true,
    middleware_hosts    => [ 'broker1.example.com' ],
    middleware_ssl      => true,
    middleware_ssl_cert => "/var/lib/puppet/ssl/certs/${::clientcert}.pem",
    middleware_ssl_key  => "/var/lib/puppet/ssl/private_keys/${::clientcert}.pem",
    middleware_ssl_ca   => "/var/lib/puppet/ssl/certs/ca.pem",
    securityprovider    => 'ssl',
    ssl_client_certs    => 'puppet:///modules/site_mcollective/client_certs',
    ssl_ca_cert         => 'puppet:///modules/site_mcollective/certs/ca.pem',
    ssl_server_public   => 'puppet:///modules/site_mcollective/certs/server.pem',
    ssl_server_private  => 'puppet:///modules/site_mcollective/private_keys/server.pem',
  }

  mcollective::user { 'vagrant':
    certificate => 'puppet:///modules/site_mcollective/client_certs/vagrant.pem',
    private_key => 'puppet:///modules/site_mcollective/private_keys/vagrant.pem',
  }
}

I'd like to secure the transport channel and authenticate users with just their private key, how do I do that?

The Mcollective standard deployment guide uses the 'ssl' securityprovider to handle authentication. If you're interested in performing the authentication without creating SSL certificates for each user, one alternative is to use the 'sshkey' securityprovider. As far as the transport channel encryption goes, it's no different than the above example's use of 'middleware_ssl*' parameters.

Sshkey adds additional flexibility with regards to deployment as it currently supports both a static and a dynamic key management philosophy. You can seperate sshkey from your normal system authentication's backend (known_hosts / authorized_keys) and permit it to send and record its key data for you. If you do this, you should strongly consider using an authorization plugin with mcollective. Alternatively, you can use puppet to enforce the available set of key data to use with requests and responses. Because this could reuse an existing user's ssh private key, it could work along-side your existing user management module.

The use of sshkey is optional. For further information, you can review a sample deployment in the /examples folder, review the sshkey module documentation, and review the sshkeyauth rubygem documentation (helpful for debugging errors).

Reference

The ::mcollective:: class

The mcollective class is the main entry point to the module. From here you can configure the behaviour of your mcollective install of server, client, and middleware.

Parameters

The following parameters are available to the mcollective class:

server

Boolean: defaults to true. Whether to install the mcollective server on this node.

client

Boolean: defaults to false. Whether to install the mcollective client application on this node.

rabbitmq_vhost

String: defaults to '/mcollective'. The vhost to connect to/manage when using rabbitmq middleware.

manage_packages

Boolean: defaults to true. Whether to install mcollective and mcollective- client packages when installing the server and client components.

version

String: defaults to 'present'. What version of packages to ensure when mcollective::manage_packages is true.

client_package

String: defaults to 'mcollective-client'. The name of the package to install for the client part. In the case that there is only one package package handling both, client and server, give the same name for 'client_package' and 'server_package'.

server_package

String: defaults to 'mcollective'. The name of the package to install for the server. In the case that there is only one package package handling both, client and server, give the same name for 'client_package' and 'server_package'.

ruby_stomp_ensure

String: defaults to 'installed'. What version of the ruby-stomp package to ensure when mcollective::manage_packages is true. Only relevant on the Debian OS family.

main_collective

String: defaults to 'mcollective'. The name of the main collective for this client/server.

collectives

String: defaults to 'mcollective'. Comma seperated list of collectives this server should join.

connector

String: defaults to 'activemq'. Name of the connector plugin to use.

Currently supported are activemq, rabbitmq, and redis

securityprovider

String: defaults to 'psk'. Name of the security provider plugin to use. 'ssl' is recommended but requires some additional setup.

psk

String: defaults to 'changemeplease'. Used by the 'psk' security provider as the pre-shared key to secure the collective with.

factsource

String: defaults to 'yaml'. Name of the factsource plugin to use on the server.

fact_cron_splay

Boolean: defaults to false. Spread the cron tasks so that not all the nodes runs the facter cronjob at the exact same time.

yaml_fact_path

String: defaults to '/etc/mcollective/facts.yaml'. Name of the file the 'yaml' factsource plugin should load facts from.

ruby_interpreter

String: defaults to '/usr/bin/env ruby' for non PE installations, and to '/opt/puppet/bin/ruby' for PE installations. With factsource 'yaml', a ruby script is installed as cron job, which needs to find the ruby interpreter. This parameter allows overriding the default interpreter.

classesfile

String: defaults to '/var/lib/puppet/state/classes.txt'. Name of the file the server will load the configuration management class for filtering.

rpcauthprovider

String: defaults to 'action_policy'. Name of the RPC Auth Provider to use on the server.

rpcauditprovider

String: defaults to 'logfile'. Name of the RPC Audit Provider to use on the server.

rpcauditlogfile

String: defaults to '/var/log/mcollective-audit.log'. Name of the audit logfile.

registration

String: defaults to undef. Name of the registration plugin to use on the server.

core_libdir

String: default is based on platform. Path to the core plugins that are installed by the mcollective-common package.

site_libdir

String: default is based on platform. Path to the site-specific plugins that the mcollective::plugin type will install with its source parameter.

This path will be managed and purged by puppet, so don't point it at core_libdir or any other non-dedicated path.

middleware_hosts

Array of strings: defaults to []. Where the middleware servers this client/server should talk to are.

middleware_user

String: defaults to 'mcollective'. Username to use when connecting to the middleware.

middleware_password

String: defaults to 'marionette'. Password to use when connecting to the middleware.

middleware_multiple_ports

Boolean: defaults to false. Wheter to use different ports for each host defined in middleware_hosts list.

middleware_port

String: defaults to '61613' (for activemq). Port number to use when connecting to the middleware over an unencrypted connection.

middleware_ssl_port

String: defaults to '61614'. Port number to use when connecting to the middleware over a ssl connection.

middleware_ports

Array of strings: defaults to ['61613'] (for activemq). List of port numbers to use when connecting to the middleware over an unencrypted connection. Port defined in the array position i will be assigned to the host defined in the same position in middleware_hosts key.

middleware_ssl_ports

Array of strings: defaults to ['61614']. List of ports numbers to use when connecting to the middleware over a ssl connection. Port defined in the array position i will be assigned to the host defined in the same position in middleware_hosts key.

middleware_ssl

Boolean: defaults to false. Whether to talk to the middleware over a ssl protected channel. Highly recommended. Requires mcollective::ssl_ca_cert, mcollective::ssl_server_public, mcollective::ssl_server_private parameters for the server/client install.

middleware_admin_user

String: defaults to 'admin'. Username for the middleware admin user.

middleware_admin_password

String: defaults to 'secret'. Password to for the middleware admin user.

server_config_file

String: default is '$confdir/server.cfg'. Path to the server configuration file.

server_logfile

String: defaults to '/var/log/mcollective.log'. Logfile the mcollective server should log to.

server_loglevel

String: defaults to 'info'. Level the mcollective server should log at.

server_daemonize

Boolean: defaults to true. Should the mcollective server daemonize when started.

client_config_file

String: defaults to '$confdir/client.cfg'. Path to the client configuration file.

client_logger_type

String: defaults to 'console'. What type of logger the client should use.

client_loglevel

String: defaults to 'warn'. Level the mcollective client should log at.

ssl_ca_cert

String: defaults to undef. A file source that points to the ca certificate used to manage the ssl keys of the mcollective install.

ssl_server_public

String: defaults to undef. A file source that points to the public key or certificate of the server keypair.

ssl_server_private

String: defaults to undef. A file source that points to the private key of the server keypair.

ssl_client_certs

String: defaults to 'puppet:///modules/mcollective/empty'. A file source that contains a directory of user certificates which are used by the ssl security provider in authenticating user requests.

sshkey_server_learn_public_keys

Boolean: defaults to false. Allow writing sshkey public keys to sshkey_server_publickey_dir.

sshkey_server_overwrite_stored_keys

Boolean: defaults to false. Overwrite learned keys.

sshkey_server_publickey_dir

String: defaults to ${confdir}/sshkey_pubdir. Directory to store received keys

sshkey_server_private_key

String: defaults to '/etc/ssh/ssh_host_rsa_key'. The private key used to sign replies with.

sshkey_server_authorized_keys

String: defaults to undefined. The authorized_key file to use. Undefined is interpreted by sshkey to mean the caller's authorized key file.

sshkey_server_send_key

String: defaults to undefined. Specifies the public key sent back with the response for validation. You probably want '/etc/ssh/ssh_host_rsa_key.pub'.

mcollective::user defined type

mcollective::user installs a client configuration and any needed client certificates in a users home directory.

Parameters

username

String: defaults to $name. The username of the user to install for.

group

String: defaults to $name. The group of the user to install for.

homedir

String: defaults to "/home/${name}". The home directory of the user to install for.

certificate

String: defaults to undef. A file source for the certificate of the user. Used by the 'ssl' securityprovider to set the identity of the user. This is mutually exclusive with certificate_content.

certificate_content

String: defaults to undef. The file content for the certificate of the user. Used by the 'ssl' securityprovider to set the identity of the user. This is mutually exclusive with certificate.

private_key

String: defaults to undef. A file source for the private key of the user. Used by the 'ssl' & 'sshkey' securityprovider to sign messages as from this user. When not supplied to sshkey, this is interpreted to use the user's ssh-agent. This is mutually exclusive with private_key_content.

private_key_content

String: defaults to undef. The file content for the private key of the user. Used by the 'ssl' & 'sshkey' securityprovider to sign messages as from this user. This is mutually exclusive with private_key.

sshkey_learn_public_keys

Boolean: defaults to false. Allow writing sshkey public keys to sshkey_client_publickey_dir.

sshkey_overwrite_stored_keys

Boolean: defaults to false. Overwrite learned keys.

sshkey_publickey_dir

String: defaults to ${homedir}/.mcollective.d/public_keys. Directory to store received keys.

sshkey_enable_private_key

Boolean: defaults to false. Enable manual specification of the private key to sign requests with. False is interpreted by sshkey to use the user's ssh-agent.

sshkey_known_hosts

String: defaults to '${homedir}/${callerid}/.ssh/known_hosts'. The known_hosts file to use. This is mutually exclusive with sshkey_publickey_dir and is disabled by sshkey_learn_public_keys.

sshkey_enable_send_key

Boolean: defaults to false. Enable sending the user public key inside the request.

mcollective::plugin defined type

mcollective::plugin installs a plugin from a source uri or a package. When installing from a source uri the plugin will be copied to mcollective::site_libdir

mcollective::plugin { 'puppet':
  package => true,
}

When installing a plugin from source you need to create the correct directory structure for it to work.

For example if you wish to sync an agent for apt which ships with apt.ddl and apt.rb you need to create the following structure:

site_mcollective/files/plugins/apt/
                               โ””โ”€โ”€ mcollective
                                   โ””โ”€โ”€ agent
                                       โ”œโ”€โ”€ apt.ddl
                                       โ””โ”€โ”€ apt.rb

Now you can then point the source attribute of the defined type to the apt folder in your plugins directory.

mcollective::plugin { 'apt':
  source => 'puppet:///modules/site_mcollective/plugins/apt',
}

For more examples have a look at the directory structure in files/plugins of this module.

Parameters

name

String: the resource title. The base name of the plugin to install.

source

String: will default to "puppet:///modules/mcollective/plugins/${name}". The source uri that will be copied to mcollective::site_libdir

package

Boolean: defaults to false. Whether to install the plugin from a file copy or a package install.

type

String: defaults to 'agent'. The type of the plugin package to install.

has_client

Boolean: defaults to true. When installing from a package, whether to attempt to install mcollective-${name}-client on the client node.

mcollective::actionpolicy defined type

mcollective::actionpolicy configures an agent for use with actionpolicy in conjunction with mcollective::actionpolicy::rule.

Parameters

name

String: the resource title. The name of the agent to set up an actionpolicy for.

default

String: defaults to 'deny'. The default actionpolicy to apply to the agent.

mcollective::actionpolicy::rule defined type

mcollective::actionpolicy::rule represents a single actionpolicy policy entry. See the actionpolicy plugin Policy File Format for specific restrictions on the values of these fields.

Parameters

name

String: the resource title. A descriptive name for the rule you are adding.

agent

String: required, no default. The name of the agent you are adding a rule for.

action

String: defaults to 'allow'. What to do when the other conditions of this line are matched.

callerid

String: defaults to '*'. What callerids should match this rule.

actions

String: defaults to '*'. What actions should match this rule.

fact_filter

String: defaults to ''. What facts should match this rule. This can be either '', a space-separated list of fact=value pairs (which match if every listed fact matches), or any valid compound filter string. This matches the "facts" field of the policy file lines.

classes

String: defaults to '*'. What classes should match this rule.

mcollective::common::setting defined type

mcollective::common::setting declares a setting that is common between server and client.

Parameters

setting

String: defaults to the resource title. The name of the setting to set.

value

String: no default. The value to set.

order

String: default '10'. The order in which to merge this setting.

mcollective::server::setting defined type

mcollective::server::setting declares a setting that is exclusive to a server.

Parameters

setting

String: defaults to the resource title. The name of the setting to set.

value

String: no default. The value to set.

order

String: default '30'. The order in which to merge this setting.

mcollective::client::setting defined type

mcollective::client::setting declares a setting that is common to clients and users.

Parameters

setting

String: defaults to the resource title. The name of the setting to set.

value

String: no default. The value to set.

order

String: default '30'. The order in which to merge this setting.

mcollective::user::setting defined type

mcollective::user::setting declares a setting that is specific to a user.

Parameters

username

String: required, no default. Which user to set this value for.

setting

String: required, no default. The name of the setting to set.

value

String: no default. The value to set.

order

String: default '70'. The order in which to merge this setting.

mcollective::server::config::factsource::yaml private class

mcollective::server::config::factsource::yaml is the class that implements cron-based fact generation and configures MCollective to use it. It is a private class and so may not be declared directly, but rather is invoked when the mcollective class is declared with the factsource parameter set to yaml (the default). Although mcollective::server::config::factsource::yaml is private it does have one parameter which can be tuned using data bindings (e.g. Hiera).

Parameters

path

String: default $::path. What PATH environment variable to use when refresh-mcollective-metadata is invoked by cron.

Configuration merging

The configuration of the server and client are built up from the various calls to mcollective::common::setting, mcollective::server::setting, mcollective::client::setting, and mcollective::user::setting.

Settings for the server will be a merge of mcollective::common::setting and mcollective::server::setting, highest order of the setting wins.

Settings for the client will be a merge of mcollective::common::setting, and mcollective::client::setting, highest order of the setting wins.

Settings for a specific user will be a merge of mcollective::common::setting, mcollective::client::setting and mcollective::user::setting for that specific user, highest order of setting wins.

Overriding existing options

You can override an existing server setting from outside of the module by simply specifying that setting again with a higher order than the default of that type, for example to make a server's loglevel be debug (without simply setting mcollective::server_loglevel) you could write:

mcollective::server::setting { 'override loglevel':
  setting => 'loglevel',
  value   => 'debug',
  order   => '50',
}

Troubleshooting

Why do I have no client.cfg?

I said to install the client, so why when I run mco ping am I seeing this:

$ mco ping
Failed to generate application list: RuntimeError: Cannot find config file '/etc/mcollective/client.cfg'

You've enabled the ssl security provider, which implies each user will have their own ssl credentials to use in the collective. In order to avoid incomplete configuration of clients in this mode we delete the system-wide /etc/mcollective/client.cfg and only generate user configuration files with the mcollective::user definition.

Limitations

This module has been built on and tested against Puppet 3.0 and higher.

The module has been tested on:

  • CentOS 6
  • Ubuntu 12.04

Testing on other platforms has been light and cannot be guaranteed.

Development

Puppet Community modules on are open projects, and community contributions are essential for keeping them great. We canโ€™t access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve.

We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.

You can read the complete module contribution guide on the Puppet Labs wiki.

Current build status is: Build Status

puppet-mcollective's People

Contributors

alexjfisher avatar antaflos avatar bastelfreak avatar bbriggs avatar blkperl avatar ccaum avatar davids avatar dhollinger avatar dhoppe avatar ffrank avatar hakamadare avatar hunner avatar igalic avatar jantman avatar jasperla avatar jhg03a avatar jyaworski avatar maxmorlocke avatar mcanevet avatar nibalizer avatar petems avatar pythianjoseph avatar reidmv avatar rhoml avatar richardc avatar roman-mueller avatar rwaffen avatar tampakrap avatar vinzent avatar wyardley avatar

Stargazers

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

Watchers

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

puppet-mcollective's Issues

Modulefile missing attributes which causes issues for puppet module command after

After you install the mcollective module using puppet module install you get this message afterwards:

$ puppet module list --modulepath modules/
Error: No source module metadata provided for mcollective

This is because the Modulefile is missing some of the attributes like source, license, etc, and when metadata.json is read afterwards module face throws that error.

Use of $facts in mcollective::actionpolicy::rule conflicts with puppet's Trusted Facts feature

See http://docs.puppetlabs.com/puppet/3.6/reference/lang_facts_and_builtin_vars.html#trusted-facts

When one sets trusted_node_data = true in puppet.conf, you also enable the "facts" hash: http://docs.puppetlabs.com/puppet/3.6/reference/lang_facts_and_builtin_vars.html#the-facts-hash

This results in an error:

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Attempt to assign to a reserved variable name: 'facts' at /etc/puppet/environments/production/modules/mcollective/manifests/actionpolicy/rule.pp:2 on node puppetmaster

datacat collector errors

@richardc

Using master branch of activemq and datacat.

  class { '::mcollective':
    middleware       => true,
    middleware_hosts => [ $::fqdn ],
  }

Output:

Error: /Stage[main]/Mcollective::Common::Config/Datacat_collector[mcollective::site_libdir]: Could not evaluate: index 7465 out of string
Notice: /Stage[main]/Mcollective::Common::Config/File[/usr/local/share/mcollective]: Dependency Datacat_collector[mcollective::site_libdir] has failures: true
Warning: /Stage[main]/Mcollective::Common::Config/File[/usr/local/share/mcollective]: Skipping because of failed dependencies
Error: /Stage[main]/Mcollective::Server::Config/Datacat[mcollective::server]/Datacat_collector[mcollective::server]: Could not evaluate: index 16041 out of string
Notice: /Stage[main]/Mcollective::Server::Config/Datacat[mcollective::server]/File[mcollective::server]: Dependency Datacat_collector[mcollective::server] has failures: true
Warning: /Stage[main]/Mcollective::Server::Config/Datacat[mcollective::server]/File[mcollective::server]: Skipping because of failed dependencies
Notice: /Stage[main]/Mcollective::Common/Anchor[mcollective::common::end]: Dependency Datacat_collector[mcollective::site_libdir] has failures: true
Warning: /Stage[main]/Mcollective::Common/Anchor[mcollective::common::end]: Skipping because of failed dependencies
Notice: /Stage[main]/Mcollective::Server::Service/Service[mcollective]: Dependency Datacat_collector[mcollective::server] has failures: true
Warning: /Stage[main]/Mcollective::Server::Service/Service[mcollective]: Skipping because of failed dependencies
Notice: /Stage[main]/Mcollective::Server/Anchor[mcollective::server::end]: Dependency Datacat_collector[mcollective::server] has failures: true
Warning: /Stage[main]/Mcollective::Server/Anchor[mcollective::server::end]: Skipping because of failed dependencies
Notice: /Stage[main]/Mcollective/Anchor[mcollective::end]: Dependency Datacat_collector[mcollective::site_libdir] has failures: true
Notice: /Stage[main]/Mcollective/Anchor[mcollective::end]: DependencyDatacat_collector[mcollective::server] has failures: true
Warning: /Stage[main]/Mcollective/Anchor[mcollective::end]: Skipping because of failed dependencies

spec system tests fail on ubuntu

Nagios issue is solved by adding a -i to the sudo command

Failures:

1) single node setup: root can do what they like shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"mco rpc rpcutil inventory -j </dev/null", :command=>"mco rpc rpcutil inventory -j </dev/null"}) stdout
Failure/Error: its(:stdout) { should =~ /discovery/ }
expected: /discovery/
got: "[{\"data\":{\"data_plugins\":null,\"version\":null,\"collectives\":null,\"classes\":null,\"main_collective\":null,\"facts\":null,\"agents\":null},\"statuscode\":1,\"action\":\"inventory\",\"sender\":\"main.foo.vm\",\"statusmsg\":\"You are not authorized to call this agent or action.\",\"agent\":\"rpcutil\"}]\n" (using =~)
Diff:
@@ -1,2 +1,2 @@
-/discovery/
+[{"data":{"data_plugins":null,"version":null,"collectives":null,"classes":null,"main_collective":null,"facts":null,"agents":null},"statuscode":1,"action":"inventory","sender":"main.foo.vm","statusmsg":"You are not authorized to call this agent or action.","agent":"rpcutil"}]
# ./spec/system/end_to_end_spec.rb:17:in `block (4 levels) in <top (required)>'

2) single node setup: root can do what they like shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"mco rpc nrpe runcommand command=hello_world -j </dev/null", :command=>"mco rpc nrpe runcommand command=hello_world -j </dev/null"}) stdout
Failure/Error: its(:stdout) { should =~ /Hello World!/ }
expected: /Hello World!/
got: "[{\"data\":{\"exitcode\":3,\"perfdata\":\"\",\"command\":\"\",\"output\":\"\"},\"statuscode\":1,\"action\":\"runcommand\",\"sender\":\"main.foo.vm\",\"statusmsg\":\"You are not authorized to call this agent or action.\",\"agent\":\"nrpe\"}]\n" (using =~)
Diff:
@@ -1,2 +1,2 @@
-/Hello World!/
+[{"data":{"exitcode":3,"perfdata":"","command":"","output":""},"statuscode":1,"action":"runcommand","sender":"main.foo.vm","statusmsg":"You are not authorized to call this agent or action.","agent":"nrpe"}]
# ./spec/system/end_to_end_spec.rb:21:in `block (4 levels) in <top (required)>'

3) single node setup: nagios user can do limited things shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"sudo -u nagios mco ping", :command=>"sudo -u nagios mco ping"}) stdout
Failure/Error: its(:stdout) { should =~ /main.foo.vm/ }
expected: /main.foo.vm/
got: "" (using =~)
Diff:
@@ -1,2 +1,2 @@
-/main.foo.vm/
+""
# ./spec/system/end_to_end_spec.rb:27:in `block (4 levels) in <top (required)>'

4) single node setup: nagios user can do limited things shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"sudo -u nagios mco rpc rpcutil inventory -j </dev/null", :command=>"sudo -u nagios mco rpc rpcutil inventory -j </dev/null"}) stdout
Failure/Error: its(:stdout) { should =~ /You are not authorized to call this agent or action/ }
expected: /You are not authorized to call this agent or action/
got: "" (using =~)
Diff:
@@ -1,2 +1,2 @@
-/You are not authorized to call this agent or action/
+""
# ./spec/system/end_to_end_spec.rb:31:in `block (4 levels) in <top (required)>'

5) single node setup: nagios user can do limited things shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"sudo -u nagios mco rpc nrpe runcommand command=hello_world -j </dev/null", :command=>"sudo -u nagios mco rpc nrpe runcommand command=hello_world -j </dev/null"}) stdout
Failure/Error: its(:stdout) { should =~ /Hello World!/ }
expected: /Hello World!/
got: "" (using =~)
Diff:
@@ -1,2 +1,2 @@
-/Hello World!/
+""
# ./spec/system/end_to_end_spec.rb:35:in `block (4 levels) in <top (required)>'

Finished in 6 minutes 4 seconds
7 examples, 5 failures

Failed examples:

rspec ./spec/system/end_to_end_spec.rb:17 # single node setup: root can do what they like shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"mco rpc rpcutil inventory -j </dev/null", :command=>"mco rpc rpcutil inventory -j </dev/null"}) stdout
rspec ./spec/system/end_to_end_spec.rb:21 # single node setup: root can do what they like shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"mco rpc nrpe runcommand command=hello_world -j </dev/null", :command=>"mco rpc nrpe runcommand command=hello_world -j </dev/null"}) stdout
rspec ./spec/system/end_to_end_spec.rb:27 # single node setup: nagios user can do limited things shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"sudo -u nagios mco ping", :command=>"sudo -u nagios mco ping"}) stdout
rspec ./spec/system/end_to_end_spec.rb:31 # single node setup: nagios user can do limited things shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"sudo -u nagios mco rpc rpcutil inventory -j </dev/null", :command=>"sudo -u nagios mco rpc rpcutil inventory -j </dev/null"}) stdout
rspec ./spec/system/end_to_end_spec.rb:35 # single node setup: nagios user can do limited things shell({:node=>main.foo.vm, :n=>main.foo.vm, :timeout=>0, :lazy=>true, :c=>"sudo -u nagios mco rpc nrpe runcommand command=hello_world -j </dev/null", :command=>"sudo -u nagios mco rpc nrpe runcommand command=hello_world -j </dev/null"}) stdout
/usr/bin/ruby1.9.1 -S rspec spec/system/end_to_end_spec.rb --require rspec-system/formatter --format=RSpecSystem::Formatter failed

mcollective::actionpolicy issue (default field)

Hi all,
just started to use this module so I don't know if this is my issue or what, but I'm trying to use this declaration in a node manifest, after mcollective:

  mcollective::actionpolicy { 'nrpe':
    default => 'deny',
  }

but no matter what I try, I always get this error:
Err: Could not retrieve catalog from remote server: Error 400 on SERVER: Syntax error at 'default'; expected '}'

I tried to follow exactly the docs, without success, so I'm wondering if this is an issue or not.
puppetversion => 2.7.23

The middleware parameter is not a boolean

The middleware parameter is not a boolean if it accepts activemq, rabbitmq, and redis as options.

It makes more sense to have a class for this.

class { 'mcollective::middleware':
  provider => 'rabbitmq',
}

mcollective::plugin isn't dependent on mcollective

With this PDSL:

  class {'mcollective':  }

  mcollective::plugin { 'puppet':
    package => true,
  }

I end up getting package installation before the mcollective class runs, and installs mcollective.

If i try to use a chain ( -> ) / require => Class['mcollective'] I get:
Error: Could not apply complete catalog: Found 1 dependency cycle:
(Anchor[mcollective::end] => Class[Mcollective] => Mcollective::Plugin[puppet] => Package[mcollective-puppet-agent] => Class[Mcollective::Server::Service] => Service[mcollective] => Class[Mcollective::Server::Service] => Anchor[mcollective::server::end] => Class[Mcollective::Server] => Anchor[mcollective::end])

This matters because I may want to install a specific version of the mcollective packages

refresh-mcollective-metadata creates superfluous emails for spurious facter errors

Some facter modules can cause temporary errors with output like

From: [email protected] (Cron Daemon)
To: [email protected]
Subject: Cron <root@bka-001-10> /usr/share/mcollective/plugins/refresh-mcollective-metadata
Content-Type: text/plain; charset=ANSI_X3.4-1968
X-Cron-Env: <PATH=/opt/puppet/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/lib64/fluent/ruby/bin:/usr/lib/fluent/ruby/bin>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <LOGNAME=root>
Message-Id: <[email protected]>
Date: Mon, 27 Apr 2015 15:15:05 +0200

Device "veth767d43e4-9" does not exist.
Device "veth767d43e4-9" does not exist.
Device "veth767d43e4-9" does not exist.
Device "veth767d43e4-9" does not exist.
Device "veth767d43e4-9" does not exist.
Device "veth78e0975b-8" does not exist.
Device "veth78e0975b-8" does not exist.
Device "veth78e0975b-8" does not exist.
Device "veth78e0975b-8" does not exist.
Device "veth78e0975b-8" does not exist.
Device "veth767d43e4-9" does not exist.
Device "veth767d43e4-9" does not exist.
Device "veth78e0975b-8" does not exist.
Device "veth78e0975b-8" does not exist.

shown for a single run.

This has been discussed in the past (e.g. https://projects.puppetlabs.com/issues/15035) but apparently seems to be unfixed in recent facter versions (in our case: 2.4.1-1puppetlabs1)

It would be great if the cronjob would be silenced by default (> /dev/null 2>&1)

Illegal attempt to assign via [index/key]

simply defining:

class { '::mcollective':
    middleware_hosts   => 'broker.example.com',
    middleware_ssl     => true,
    securityprovider   => 'ssl',
    ssl_client_certs   => 'puppet:///modules/mcollective_site/admin_certs',
    ssl_ca_cert        => 'puppet:///modules/mcollective_site/certs/ca.pem',
    ssl_server_public  => 'puppet:///modules/mcollective_site/certs/server.pem',
    ssl_server_private => 'puppet:///modules/mcollective_site/private_keys/server.pem',
}

Causes:

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Illegal attempt to assign via [index/key]. Not an assignable reference at /etc/puppet/environments/develop/modules/mcollective/manifests/setting.pp:5:3 at /etc/puppet/environments/develop/modules/mcollective/manifests/common/setting.pp:3

Should exclude "path" fact from facts.yaml

When running puppet agent -t manually on the shell of a node the values of the $PATH environment variable and thus the path fact are almost always different from when run non-manually by Cron or daemon. This results in changes in /etc/mcollective/facts.yaml, prompting a restart of Mcollective.

This leads to unnecessary noise and I think the path fact should be excluded from facts.yaml, just like other dynamic facts.

Plugin not installed?

Using this definition

class { 'mcollective':
stomp_server => $::puppet_master,
server => true,
client => false,
mc_security_provider => 'psk',
mc_security_psk => 'xxxx',
stomp_port => 6163,
stomp_passwd => 'xxxxx,
fact_source => 'yaml',
}

And getting this error

Starting mcollective: /usr/lib/ruby/site_ruby/1.8/mcollective/pluginmanager.rb:169:in load': no such file to load -- mcollective/connector/stomp.rb (LoadError) from /usr/lib/ruby/site_ruby/1.8/mcollective/pluginmanager.rb:169:inloadclass'
from /usr/lib/ruby/site_ruby/1.8/mcollective/config.rb:135:in `loadconfig'
from /usr/sbin/mcollectived:33
[FAILED]

Possible that is missing the stomp.rb that should be present in the plugin folder, have to add the plugin after this way
mcollective::plugins::plugin { 'stomp':
ensure => present,
type => 'connector',
}
But if I choose 'stomp' why the plugin does not get installed?

For ActiveMQ middleware host, manage activemq-wrapper.conf

Just came in to work this morning to find that my MCollective instance had run out of heap space and gone somewhat crazy, preventing puppet runs throughout my environment and spamming notifications.

While this module support replacing the activemq.xml config with either a different template or a string, it doesn't manage activemq-wrapper.conf (on centos6, /usr/share/activemq/conf/activemq-wrapper.conf) at all, which is where we need to set (a) the actual initial and maximum heap space, and (b) enable JMX so we can actually monitor this.

Plugin type should allow plugin deployment without modification

Overview

Currently, to deploy plugins not already included in the module, the module itself must be modified by adding files to the module's fileserver mount point.

To better support re-usability, the defined resouce type should allow passing in URL's or file contents from a "site" module or something equivalent.

Adding mcollective plugins should require no modification to the module.

puppet 4.2 / puppet-agent-1.2 no longer use Ruby-based facter

The cronjob /opt/puppetlabs/mcollective/plugins/refresh-mcollective-metadata fails with Puppet 4.2.0 / Facter 3.0.1 because of

/opt/puppetlabs/puppet/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- facter/application (LoadError)
    from /opt/puppetlabs/puppet/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /opt/puppetlabs/mcollective/plugins/refresh-mcollective-metadata:4:in `<main>'

And quite rightly the path /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/facter no longer exists because the rewritten facter version 3 in C no longer requires any of those Ruby files.

My local workaround in the mcollective module is to replace the existing cronjob with facter --yaml >/etc/puppetlabs/mcollective/facts.yaml every 15 minutes.

Do you feel this is an appropriate solution for the module if wrapped in a if facterversion > 3 condition? I'll prepare a PR if so.

Cheers,
Gavin.

factsource crontab PATH conflicting with other cronjobs

https://github.com/puppet-community/puppet-mcollective/blob/master/manifests/server/config/factsource/yaml.pp#L20

apparently, ENV variables set in crontab are global for all cronjobs. I actually run puppet via cron (https://github.com/theforeman/puppet-puppet/blob/master/manifests/agent/service.pp#L38)

now every Puppet run bloats my PATH variable a little more until it looks like this:

X-Cron-Env: <PATH=/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin:/opt/puppet/bin...

Exec[create-mcollective-metadata] in mcollective::server::config::factsource::yaml never runs for mcollective>=2.5.0

Exec[create-mcollective-metadata] in mcollective::server::config::factsource::yaml never runs for mcollective>=2.5.0. At least from the Puppetlabs repo. mcollective=2.0.0 from ubuntu (trusty) does not have this issue.

This is because the Exec uses$mcollective::yaml_fact_path_real to determine if it should run, via the creates attribute. The Puppetlabs MCollective packages automatically creates that file post-install, however, thus denying the Exec the chance to run. As a result, facts aren't available to MCollective until the next time the Cron[refresh-mcollective-metadata] is run.

Not sure how to tackle this issue, but I'd be OK with the Exec running only via a Refresh event from mcollective::server::setting{factsource}

`collectives` parameter should be an array

currently collectives is a "Comma seperated list of collectives".

This makes it hard to override the parameter hierarchically.
We should change it to an array, while keeping the string for backwards compatibility.

sensitive information leakage into facts.yaml

Puppet 3.3.0, mcollective module version v1.0.0

The facts.yaml contains all sorts of bad things that shouldn't be there:

  activemq_confdir: /etc/activemq/instances-available/mcollective
  activemq_console: false
  activemq_template: mcollective/activemq.xml.erb
  before: !ruby/object:Puppet::Resource
    title: "mcollective::server::config::end"
    reference: "Anchor[mcollective::server::config::end]"
    type: Anchor
    tags:
      - anchor
      - "mcollective::server::config::end"
      - mcollective
      - server
      - config
      - end
    is_class: false
    parameters: {}
  client: true
  client_config_file: /etc/mcollective/client.cfg
  client_logger_type: console
  client_loglevel: warn
  middleware_password: marionette
  middleware_port: "61613"
  middleware_ssl: false
  middleware_ssl_port: "61614"
  middleware_user: mcollective

Can't immediately see how this scope leaks in there

docs: middle ware parameter [how to connect mcollective with a middleware]

node puppet {
  class { '::mcollective':
    client           => true,
    middleware       => true,
    middleware_hosts => ['puppet.domain1.net'],
  }
}

using this on puppet master to install mcollective and it's not working because it says "middleware" parameter is not valid?

Invalid parameter middleware on Class[Mcollective] at /etc/puppet/manifests/site.pp:6 on node puppet.salesseek.net

mco client needs cert, key and ca to issue commands in case of middleware_ssl

If we set middleware_ssl to true, mco client can't ping because of those errors:

mco ping
error 2014/03/11 13:14:22: activemq.rb:306:in `ssl_parameters' Failed to set full SSL verified mode: RuntimeError: cert, key and ca has to be supplied for verified SSL mode

The ping application failed to run, use -v for full error backtrace details: Could not connect to ActiveMQ Server: cert, key and ca has to be supplied for verified SSL mode

Fix:
move cert and key configuration from server to common class:

mcollective::server::setting { "plugin.activemq.pool.${name}.ssl.cert and key
mcollective::common::setting { "plugin.activemq.pool.${name}.ssl.cert and key

Error thrown about rabbitmq, but seems to work anyhow

In the wake of the resolution to #86, installing mcollective using rabbitmq...

# /etc/puppet/manifests/site.pp
node 'dopey.example.com' {
    class { '::mcollective':
    client                    => true,
    middleware                => true,
    middleware_hosts          => [ 'dopey.example.com'],
    delete_guest_user         => true,
    connector                 => 'rabbitmq',
  }
  mcollective::user { 'joe':}

This happens:

Error: Could not prefetch rabbitmq_exchange provider 'rabbitmqadmin': Execution of '/usr/local/bin/rabbitmqadmin list exchanges' returned 1: *** Access refused: /api/exchanges

However, sudo mco ping works as expected. The delete_guest_user doesn't make any difference on or off.

Using rabbitmq does not work

Here is /etc/puppet/manifests/site.pp

node 'sleepy' {
  class { '::mcollective':
    client                    => true,
    middleware                => true,
    middleware_hosts          => [ 'doc.example.com'],
    delete_guest_user         => true,
    connector                 => 'rabbitmq',
}

Here are the results

Error: Could not prefetch rabbitmq_exchange provider 'rabbitmqadmin': Execution of '/usr/local/bin/rabbitmqadmin list exchanges' returned 1: *** Access refused: /api/exchanges

Error: Execution of '/usr/local/bin/rabbitmqadmin declare exchange --vhost=/mcollective name=mcollective_broadcast type=topic' returned 1: *** Access refused: /api/exchanges/%2Fmcollective/mcollective_broadcast

Error: /Stage[main]/Mcollective::Middleware::Rabbitmq/Rabbitmq_exchange[mcollective_broadcast@/mcollective]/ensure: change from absent to present failed: Execution of '/usr/local/bin/rabbitmqadmin declare exchange --vhost=/mcollective name=mcollective_broadcast type=topic' returned 1: *** Access refused: /api/exchanges/%2Fmcollective/mcollective_broadcast

Presence or absence of "delete_guest_user" makes no difference.

Module classes should be contained

The mcollective module should declare classes in a manner that contains all of the resource.

This is required to support this before and require use of the module:

node default {

  # The default behavior is to configure the server only and not the client.
  # The following PSK and Server settings are the defaults, but you may
  # want to change them for your site.
  notify { "alpha":
    message => "alpha",
  }
  ->
  class { 'java': }
  ->
  class { 'activemq': }
  ->
  class { 'mcollective':
    mc_security_psk => 'changemeplease',
    stomp_server    => 'stomp',
    server          => true,
    client          => true,
  }
  ->
  notify { "omega":
    message => "omega",
  }

}

mcollective::plugins::plugin is insular

So mcollective::plugins::plugin is insular in the sense that it can manage plugins inside the mcollective module - but nothing external. Plugin developers would be unable to use this themselves - and would be forced to add their own plugins to the mcollective module after download.

I'd change 2 things:

  • Allow users to override the default source ... its good to have them install plugins always in the same place each time obviously (so ${module_name}/files/mc_plugins or somesuch ... but I guess if you use $calling_module or have an override attribute this would be cool.
  • For external users, less nesting would look nicer as the resource is an external API then ... like mcollective::plugin instead of mcollective::plugins::plugin ... however this is more L&F then anything.

'/etc/mcollective' hardcoded in mcollective::actionpolicy.pp

FreeBSD's configuration directory is installed under '/usr/local/etc/mcollective'.

Suggested fixes.

  • Modify mcollective::actionpolicy path to use a policy_dir parameter in string interpolation.
  • Refactor all paths to use a common config_dir parameter

Puppet 4 directory layout

since puppet 4 relocated things beneath /etc/puppetlabs, there's a few things that this module might be able to do automatically. Off the top of my head:

  • confdir should be /etc/puppetlabs/mcollective instead of /etc/mcollective
  • libdir in server.cfg and the client cfg files can take multiple entries. The default that ships with the package is now
libdir = /opt/puppetlabs/mcollective/plugins

# consult the "classic" libdirs too
libdir = /usr/share/mcollective/plugins
libdir = /usr/libexec/mcollective
  • logfile default has also moved
logfile = /var/log/puppetlabs/mcollective.log

Not sure if there might be more, but those are the ones that jumped out at me.

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.