Giter VIP home page Giter VIP logo

php-formula's Introduction

php-formula

Travis CI Build Status Semantic Release

Formula to set up and configure php

WARNING: BREAKING CHANGES SINCE v1.0.0

Prior to v1.0.0, this formula provided two methods for managing PHP; the old method under php and the new method under php.ng. The old method has now been removed and php.ng has been promoted to be php in its place.

If you are not in a position to migrate, please pin your repo to the final release tag before v1.0.0, i.e. v0.40.1.

To migrate from php.ng, simply modify your pillar to promote the entire section under php:ng so that it is under php instead. So with the editor of your choice, highlight the entire section and then unindent one level. Finish by removing the ng: line.

To migrate from the old php, first convert to php.ng under v0.40.1. and then follow the steps laid out in the paragraph directly above.

See the full SaltStack Formulas installation and usage instructions.

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

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

See Formula Versioning Section for more details.

Commit message formatting is significant!!

Please see How to contribute for more details.

Please provide feedback by filing issues, discussing in #salt in Freenode and the mailing list as normal.

Note: php states require the merge parameter of salt.modules.pillar.get(), first available in the Helium release.

Installs the php package.

Installs the php-adodb package.

Meta-state that combines php.apache2.install and php.apache2.ini.

Manages the apache2 php.ini file

Installs the apache2 and libapache2-mod-php5 package. Debian Only.

Installs the php-apc package. Disabled on opensuse need server:php repo

Installs the php-apcu package. Disabled on opensuse need server:php repo

Installs the php-auth-sasl package.

Installs the php-bcmath package.

Installs the php-bz2 package.

Installs the php-cache-lite package.

Installs the php-cgi package. Disabled on opensuse only php5-fastcgi available.

Meta-state that combines php.cli.install and php.cli.ini.

Manages the php-cli ini file.

Installs the php-cli package.

Installs [composer](https://getcomposer.org) and keeps it updated.

Installs the php-console-table package.

Installs the php-ctype package.

Installs the php5-curl package on Debian, and ensures that curl itself is installed for RedHat systems, this is due to the curl libs being provided by php-common, which will get installed with the main php package.

Installs the php-dba package.

Installs the php5-dev and build-essential package.

Installs the php-filter package.

Meta-state that combines all php.fpm states.

Manages the (non-pool) php-fpm config files.

Installs the php-fpm package.

Meta-state that combines php.fpm.service and php.fpm.pools_config

Manages php-fpm pool config files.

Manages the php-fpm service.

Installs the php-gd package.

Installs the php-gearman package.

Installs the php-geoip package.

Installs the php-geshi package.

Installs the php-gettext package.

Installs the php-gmp package. Debian Only.

Installs the php-hash package.

Installs the php-http package.

Meta-state that combines php.hhvm states

Manages the php-hhvm config files

Installs the php-hhvm package

Configures the hhvm repo for debian/ubuntu

Manages the php-hhvm service.

Installs the php-igbinary package.

Installs the php-imagick package. Disabled on opensuse no package.

Installs the php-imap package.

Installs the php-intl package.

Installs the php-json package.

Installs the php-ldap package.

Installs the php-mail package.

Installs the php-mbstring package.

Installs the php-mcrypt package.

Installs the php-mdb2 package.

Installs the php-mdb2-driver-mysql package.

Installs the php-mdb2-driver-pgsql package.

Installs the php-memcache package. Disabled on opensuse need server:php:extensions repo

Installs the php-memcached package. Disabled on opensuse need server:php:extensions repo

Calls php.<name> for each entry in php:modules if available, or try to install the matching packages that can be set via from php:lookup:pkgs

Installs the php-mongo package.

Installs the php-mongodb package.

Installs the php-msgpack package.

Installs the php-mysql package.

Installs the php-mysqlnd package. Disabled on opensuse no package.

Installs the php-net-smtp package.

Installs the php-net4 package.

php.net6 ^^^^^^^^^^^NET6

Installs the php-net6 package.

Installs the php-oauth package.

Installs the php-opcache package.

Installs the php-openssl package.

Installs the php-pear package.

Installs the php-pgsql package.

Installs the php-phar package.

Installs the php-posix package.

Installs the php-pspell package.

Installs the php-readline package.

Installs the php-redis package. Disabled on opensuse need server:php:extensions repo

Installs the php-seclib package.

Installs the php-session package.

Installs the php-snmp package.

Installs the php-soap package.

Installs the php-sqlite package,

Installs the php-ssh2 package,

Installs the php-suhosin package.

Installs the php-svn package.

Installs the php-sybase package.

Installs the php-tcpdf package.

Installs the php-tidy package.

Installs the php-uuid package.

Meta-state that combines php.xcache.install and php.xcache.ini.

Manages the php-xcache ini file

Installs the php-xcache package. Disabled on opensuse need server:php:extensions repo

Installs the php-xdebug package.

Installs the php-xml package.

Installs the php-xsl package.

Installs the php-zip package.

Installs the php-zlib package.

Linux testing is done with kitchen-salt.

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

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

Creates the docker instance and runs the php main states, ready for testing.

Runs the inspec tests on the actual instance.

Removes the docker instance.

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

Gives you SSH access to the instance for manual testing.

Windows/FreeBSD/OpenBSD testing is done with kitchen-salt.

  • Ruby
  • Virtualbox
  • Vagrant
$ gem install bundler
$ bundle install --with=vagrant
$ bin/kitchen test [platform]

Where [platform] is the platform name defined in kitchen.vagrant.yml, e.g. windows-81-latest-py3.

When testing using Vagrant you must set the environment variable KITCHEN_LOCAL_YAML to kitchen.vagrant.yml. For example:

$ KITCHEN_LOCAL_YAML=kitchen.vagrant.yml bin/kitchen test      # Alternatively,
$ export KITCHEN_LOCAL_YAML=kitchen.vagrant.yml
$ bin/kitchen test

Then run the following commands as needed.

Creates the Vagrant instance and runs the php main states, ready for testing.

Runs the inspec tests on the actual instance.

Removes the Vagrant instance.

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

Gives you RDP/SSH access to the instance for manual testing.

php-formula's People

Contributors

aboe76 avatar ahummeling avatar alxwr avatar arthurzenika avatar bogdanr avatar ckng avatar dafyddj avatar danoe avatar fintanmm avatar gravyboat avatar gtmanfred avatar javierbertoli avatar kpostrup avatar kurt108 avatar mgomersbach avatar myii avatar n-rodriguez avatar nmadhok avatar pawelrosada avatar pprkut avatar puneetk avatar retrry avatar seldaek avatar semantic-release-bot avatar sticky-note avatar stp-ip avatar techhat avatar tsia avatar whiteinge avatar wwentland 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

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

php-formula's Issues

Add support for phpdbg

We should add support for the php-phpdbg package. On Ubuntu, this means e.g. a separate /etc/php/7.0/phpdbg tree and php.ini file that need to be maintained.

Ubuntu PPA must switch to main repo

The PHP 5.6 PPA is now deprecated and will generate deprecation warnings when updating. It seems like the only PPA that will be valid from now on is:

https://launchpad.net/~ondrej/+archive/ubuntu/php

This currently contains 5.5, 5.6 and 7.0. It seems that on Ubuntu 14.04, the following packages exist, for example for php-cli:-

  • php5-cli - Ubuntu default version (5.5)
  • php5.5-cli - PPA version 5.5
  • php5.6-cli - PPA version 5.6
  • php7.0-cli - PPA version 7.0
  • php-cli - PPA version that resolves to version 7.0

It probably makes sense to default the PPA name to this one and make sure that the Jinja maps are updated to resolve this sensibly. Last time I tried, they didn't seem to work for version 7.0 so this may be an opportunity to resolve this too.

php.ng.mcrypt is not enabled by default

this is a bug in the Ubuntu php5-mcrypt package, but should there be a way for this formula to list which extensions are enabled and disabled? (much like the apache formula's module handling)

Empty php:ng:fpm:pools causes cryptic error message

If you have FPM configuration files split in re-usable pieces and end up with a FPM config that has no pools for a minion (I know, it's not useful for FPM, bear with me), Salt fails with a rather nondescript message about null not being iterable. There are no pointers as to which state, file or line this happens at. I know this basically is a Salt error reporting issue, but a few checks at the right places to only call .itertitems() on stuff that's actually not empty would be a big help.

Changing pillar value php.temp_dir causes install-composer state to fail

On my machines /tmp is mounted as noexec so running the composer installer in the default location (/tmp) fails. I tried changing this to /var/tmp in my pillar files, however then a different issue occurs:

The system interprets the installer file as bash and you get output like this:

----------
          ID: install-composer
    Function: cmd.run
        Name: /var/tmp/installer --filename=composer --install-dir=/usr/local/bin
      Result: False
     Comment: Command "/var/tmp/installer --filename=composer --install-dir=/usr/local/bin" run
     Started: 03:44:52.122608
    Duration: 10.569 ms
     Changes:
              ----------
              pid:
                  21698
              retcode:
                  2
              stderr:
                  /var/tmp/installer: 1: /var/tmp/installer: cannot open ?php: No such file
                  /var/tmp/installer: 3: /var/tmp/installer: /bin: Permission denied
                  /var/tmp/installer: 4: /var/tmp/installer: *: not found
                  /var/tmp/installer: 5: /var/tmp/installer: *: not found
                  /var/tmp/installer: 6: /var/tmp/installer: Syntax error: word unexpected (expecting ")")
              stdout:

If I prefix the command with php then it works:

install-composer:
  cmd.run:
    - name: php {{ php.temp_dir }}/installer --filename={{ php.composer_bin }} --install-dir={{ php.local_bin }}
    - unless: test -f {{ install_file }}
    - require:
      - file: get-composer

It seems the formula should detect when the installer file is not executable.

High template render times

The templates are very slow to load...
Rendering map.jinja takes 0.5s and that is repeated for each php plugin requested.
So in my case fpm, mongo, mysql, curl, soap...

[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/mchc/web/php.sls' using 'jinja' renderer: 0.0007643699645996094
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/mchc/web/php.sls' using 'yaml' renderer: 0.0010766983032226562
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/php/ng/mongo.sls' using 'jinja' renderer: 0.5516741275787354
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/php/ng/mongo.sls' using 'yaml' renderer: 0.00038695335388183594
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/php/ng/curl.sls' using 'jinja' renderer: 0.5393562316894531
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/php/ng/curl.sls' using 'yaml' renderer: 0.00039315223693847656
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/php/ng/soap.sls' using 'jinja' renderer: 0.5391628742218018

I tried really hard to optimize this, by caching the map.jinja content in a variable and then re-using that variable (via pillar.get('php', {}) + .update({'cache:': php}) ), but that didn't help.
No matter what I do it takes 0.5s to render map.jinja unless I remove "from map.jinja" completely for a test.

php.ng.fpm formula won't work without pillar data

If you run the php.ng.fpm state on a minion without pillar data gives the following error:

Passed invalid arguments: 'NoneType' object is not iterable

On a debug level I found the following issue:

[DEBUG   ] Results of YAML rendering: 
OrderedDict([('include', ['php.ng.fpm.service', 'php.ng.fpm.pools_config']), ('extend', OrderedDict([('php_fpm_service', OrderedDict([('service', [OrderedDict([('watch', None)]), OrderedDict([('require', None)])])]))]))])
[INFO    ] Fetching file from saltenv 'base', ** skipped ** latest already in cache 'salt://php/ng/fpm/pools_config.sls'
[DEBUG   ] Jinja search path: ['/var/cache/salt/minion/files/base']
[DEBUG   ] Re-using SAuth for ('/etc/salt/pki/minion', 'example.home.lan', 'tcp://xxx.xxx.xxx.xxx:4506')
[INFO    ] Fetching file from saltenv 'base', ** skipped ** latest already in cache 'salt://php/ng/map.jinja'
[INFO    ] Fetching file from saltenv 'base', ** skipped ** latest already in cache 'salt://php/ng/macro.jinja'
[DEBUG   ] Rendered data from file: /var/cache/salt/minion/files/base/php/ng/fpm/pools_config.sls:
# Manages the php-fpm pools config files



# Simple path concatenation.






[DEBUG   ] Results of YAML rendering: 
{}
Passed invalid arguments: 'NoneType' object is not iterable
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/salt/cli/caller.py", line 138, in call
    ret['return'] = func(*args, **kwargs)
  File "/usr/lib/python2.7/site-packages/salt/modules/state.py", line 671, in sls
    ret = st_.state.call_high(high_)
  File "/usr/lib/python2.7/site-packages/salt/state.py", line 2027, in call_high
    high, ext_errors = self.reconcile_extend(high)
  File "/usr/lib/python2.7/site-packages/salt/state.py", line 1208, in reconcile_extend
    .extend(arg[argfirst]))
TypeError: 'NoneType' object is not iterable

So it looks like it trying to create a fpm pool without data.

I would think the state php.ng.fpm would just do nothing with pools if they aren't provided in pillar.

php.ng doesn't use PPA

From what I can see, NG doesn't use the options of use_ppa and ppa_name.

Ideally I'd like to do this, to install PHP 5.6.7 from Ondล™ej Surรฝ's excellent repo:

php:
  # Use ppa instead the default repository (only Debian family)
  use_ppa: True
  # Set the ppa name (valid only if use_ppa is not none)
  ppa_name: 'ondrej/php5-5.6'

Can anyone help me please? I'm a bit new to Salt so excuse me if I'm being dumb, or if there is a better way that I'm not seeing.

I've got an inkling that maybe I could do something within the lookup.pkgs section of the pillar, but I have no idea how, so if anyone can give me an example I'd be really grateful.

Trigger web server reload if neccessary

Is there a setting I'm missing that will already allow this? For instance when I add php.ng.mysql. I have to manually reload apache. I know people run different web servers, but maybe that information could be passed as pillar data so it knows which service to reload.

Fork out php.ng formula

Can we move the php.ng formula out to its on repo instead of keeping it in the php-formula ?
or we can move the php-formula out to php-simple formula or something less confusing then having two formulas in one dir.

ubuntu 14.04, default hhvm pid file path incorrect

from /etc/init.d/hhvm:
PIDFILE=/var/run/hhvm/pid

from the php formula map php/ng/map.jinja:
('pid', '/var/run/hhvm.pid'),

this causes hhvm not to start by default unless you add to your pillar:

  ng:
    lookup:
      hhvm:
        server:
          pid: '/var/run/hhvm/pid'

not sure if this is easily changable - other distros may break if your change the default pid pathing?

composer ng fail to install

composer ng fail to install because of missing package php but there is other package with this binary.
Should check on binary

Error with ng FPM

          ID: php_ppa_fpm
    Function: pkgrepo.managed
      Result: False
     Comment: Failed to configure repo 'php_ppa_fpm': E: Type 'php_ppa_fpm' is not known on line 17 in source list /etc/apt/sources.list
              E: The list of sources could not be read.
     Started: 17:13:43.298047
    Duration: 333.854 ms
     Changes:

It seems that this line is missing the repo name - which results in adding php_ppa_fpm into sources.list (https://github.com/saltstack-formulas/php-formula/blob/master/php/ng/installed.jinja#L38). I think it should be like in nginx formula - https://github.com/mojeskolycz/nginx-formula/blob/master/nginx/ng/pkg.sls#L14

Should I create a PR?

Issue when running highstate

I tried my own pillar and the default pillar.example, minion is running latest dev.
Tried playing with the code a bit, but really have no idea where is it imploding.

[INFO    ] Fetching file from saltenv 'base', ** skipped ** latest already in cache 'salt://php/ng/fpm/pools_config.sls'
[DEBUG   ] Jinja search path: ['/var/cache/salt/minion/files/base']
[DEBUG   ] Decrypting the current master AES key
[DEBUG   ] Loaded minion key: /etc/salt/pki/minion/minion.pem
[INFO    ] Fetching file from saltenv 'base', ** skipped ** latest already in cache 'salt://php/ng/map.jinja'
[INFO    ] Fetching file from saltenv 'base', ** skipped ** latest already in cache 'salt://php/ng/macro.jinja'
[DEBUG   ] Rendered data from file: /var/cache/salt/minion/files/base/php/ng/fpm/pools_config.sls:
# Manages the php-fpm pools config files

# Simple path concatenation.

[DEBUG   ] Results of YAML rendering: 
{}
Passed invalid arguments: 'NoneType' object is not iterable
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/salt/cli/caller.py", line 91, in call
    ret['return'] = func(*args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/salt/modules/state.py", line 287, in highstate
    whitelist=kwargs.get('whitelist')
  File "/usr/lib/python2.7/dist-packages/salt/state.py", line 2768, in call_highstate
    return self.state.call_high(high)
  File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1886, in call_high
    high, ext_errors = self.reconcile_extend(high)
  File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1156, in reconcile_extend
    .extend(arg[argfirst]))
TypeError: 'NoneType' object is not iterable

[BUG] salt generated version php.ini missing in php-cli directory, when installing php-fpm and php-cli.

I am looking for some assistance with php saltstack formula. I need php-fmp and php-cli. The php.ini file is getting built and placed in the fmp folder, but the cli version of php.ini is not getting built. I am sure I am doing something wrong but I can not put on my finger on it. Following is salt information. I will attach my pillar/php.sls file as well.

Describe the bug

I am trying to install PHP with php-fpm and php-cli. The salt managed php.ini file is written to the php-fpm directory. However, the php.ini file in the php-cli directory is the default file, rather than the salt managed version of the file.

My assumption is that I have improperly defined the php.sls file. I have been testing and have made changes to the php.sls file in an attempt to get the functionality working properly.

Setup

Running the formula using:

$ sudo salt '*worker*' state.apply php

php.zip -- extracted below as well:

# -*- coding: utf-8 -*-
# vim: ft=yaml
---
## php pillar examples

{% set phpversion = '7.0' %}
 
php:
  # Use the following values to mute deprecation warnings
  warning_messages:
    v1.0.0:
      mute_critical: true
      mute_upcoming: true
  # Use external repository instead the default (only Ubuntu family)
  use_external_repo: true
  # Set the external repository name (valid only if use_external_repo is not none)
  external_repo_name: 'ondrej/php'
  # Use Software Collections Repository offering PHP 5.4, 5.5, 5.6, 7.0 and 7.1
  # https://www.softwarecollections.org/en/ for more information.
  # SCL is only supported on RHEL and CentOS
  use_scl_repo: true
  # Which PHP version from the SCL repos to use
  scl_php_version: 71
  # Set the MongoDB driver version. You can specify (optionally) the driver version
  # when you add the php.mongo formula to your execution list
  mongo_version: "1.5.5"
  # set the version of php to be used
  version: {{ phpversion }}
  # can be a list of versions :
  # version:
  #   - "7.3"
  #   - "7.2"

  # set the version for the Debian alternatives system, when using a list of versions,
  # php:version is used otherwise.
  alternatives_version: "7.2"

  # this section contains mostly grain filtered data, while overrides
  # are possible in the pillar for unique cases, if your OS is not
  # represented, please consider adding it to the map.jinja for
  # upstream inclusion
  lookup:
    enable_php_repo: centos-sclo-rh-testing
    # package definitions, these can be strings, lists of strings, or
    # lists of dictionaries
    pkgs:
      # memcached: php5-memcached
      # ensures both will be installed
      curl:
        - php-common
        - curl
      # a dictionary can be used in more complex cases where you want
      # to pass forward special arguments to the pkg.installed call
      # you MUST include the name argument for this to work
      cli:
        -
          name: php-cli
          fromrepo: my-specialrepo
        -
          name: php-common
          skip_verify: true
      #fpm: php-fpm

     # php-fpm os-specific settings
    fpm:
      ini: /etc/php/{{ phpversion }}/fpm/php.ini
      conf: /etc/php/{{ phpversion }}/fpm/config.conf
      pools: /etc/php/{{ phpversion }}/fpm/pool.d
      service: php{{ phpversion }}-fpm

      # the default content of the php5-fpm main config file
      defaults:
        global:
          pid: /var/run/php{{ phpversion }}-fpm.pid

    # php-cli os-specific settings
    cli:
      ini: /etc/php/{{ phpversion }}/cli/php.ini

  # php-fpm settings
  fpm:
    # settings for the php-fpm service
    service:
      # if true, enables the php-fpm service, if false disables it
      enabled: true
      # additional arguments passed forward to
      # service.enabled/disabled
      opts:
        reload: true

    # settings for the relevant php-fpm configuration files
    config:

      # options to manage the php.ini file used by php-fpm
      ini:
        # arguments passed through to file.managed
        opts:
          recurse: true
        # php.ini file contents that will be merged with the
        # defaults in php.ini.defaults. See php.ini.defaults for
        # syntax guidelines.
        settings:
          PHP:
            engine: 'On'
            extension_dir: '/usr/lib/php/modules/'
            extension: [pdo_mysql.so, iconv.so, openssl.so]
            expose_php: 'Off'
            default_charset: "UTF-8"

      # options to manage the php-fpm conf file
      conf:
        # arguments passed through to file.managed
        opts:
          recurse: true
        # php-fpm conf file contents that will be merged with
        # php.lookup.fpm.defaults. See php.ini.defaults for
        # ini-style syntax guidelines.
        settings:
          global:
            pid: /var/run/fpm/special-pid.file

    # settings for fpm-pools
    pools:
      # defaults will apply for each pools settings and can be overwritten
      # by pool settings
      defaults:
        user: www-data
        group: www-data
        listen: /var/run/fpm-default.sock

      # name of the pool file to be managed, this will be appended
      # to the path specified in php.lookup.fpm.pools
      'mypool.conf':
        # If true, the pool file will be managed, if false it will be
        # absent
        enabled: true

        # Overwrite the filename for ext_pillar that doesn't allow
        # dots in fields names.
        filname: my_other_name.conf

        # arguments passed forward to file.managed or file.absent
        opts:
          replace: false

        # pool file contents. See php.ini.defaults for ini-style
        # syntax guidelines.
        settings:
          myapp:
            user: www-data
            group: www-data
            listen: /var/run/php{{ phpversion }}-fpm-myapp.sock
            listen.owner: www-data
            listen.group: www-data
            listen.mode: 0660
            pm: dynamic
            pm.max_children: 5
            pm.start_servers: 2
            pm.min_spare_servers: 1
            pm.max_spare_servers: 3
            'php_admin_value[memory_limit]': 300M

  # php-cli settings
  cli:
    # settings to manage the cli's php.ini
    config:
      ini:
        # opts passed forward directly to file.managed
        opts:
          # replace: true
        # contents of the php.ini file that are merged with defaults
        # from php.ini.defaults. See php.ini.defaults for ini-style
        # syntax guidelines
        settings:
          PHP:
            engine: 'on'
            realpath_cache_size: 16k
            memory_limit: 256M
            display_errors: stderr
            auto_prepend_file: /usr/local/share/reach/global/global.php
            include_path: ".:/usr/local/share/reach/global"
            extension: redis.so


  # php-xcache settings
  xcache:
    ini:
      opts: {}
      # contents of the xcache.ini file that are merged with defaults
      # from php.xcache.ini.defaults. See php.ini.defaults for ini-style
      settings:
        xcache:
          xcache.size: 90M

  # global php.ini settings
  ini:
    # Default php.ini contents. These follow a strict format. The top-
    # level dict keys form ini group headings. Nested key/value
    # pairs represent setting=value statements. If a value is a list,
    # its contents will be joined by commas in final rendering.
    defaults:
      PHP:
        engine: 'On'
        output_buffering: 4096
        disable_functions:
          - pcntl_alarm
          - pcntl_fork
          - pcntl_wait
          - pcntl_waitpid
          - pcntl_wifexited
          - pcntl_wifstopped
          - pcntl_wifsignaled
          - pcntl_wifcontinued
          - pcntl_wexitstatus
          - pcntl_wtermsig
          - pcntl_wstopsig
          - pcntl_signal
          - pcntl_signal_dispatch
          - pcntl_get_last_error
          - pcntl_strerror
          - pcntl_sigprocmask
          - pcntl_sigwaitinfo
          - pcntl_sigtimedwait
          - pcntl_exec
          - pcntl_getpriority
          - pcntl_setpriority
      'CLI Server':
        cli_server.color: 'On'

  # List of modules to install via php.modules
  modules:
    # Calls `php.<name>` if available, or try to install the matching
    # packages that can be set via from php:lookup:pkgs
    - cli
    - fpm
    - curl
    - mysql
    - bcmath
    - composer
    - dev
    - gd
    - gmp
    - json
    - ldap
    - mbstring
    - opcache
    - sqlite
    - sybase
    - xml
    - redis
    - pear
    - mongodb
    - mcrypt

  # When using php.apache2 on FreeBSD:
  # Set this to false if you're not using apache-formula
  use_apache_formula: true

  tofs:
    # The files_switch key serves as a selector for alternative
    # directories under the formula files directory. See TOFS pattern
    # doc for more info.
    # Note: Any value not evaluated by `config.get` will be used literally.
    # This can be used to set custom paths, as many levels deep as required.
    # files_switch:
    #   - any/path/can/be/used/here
    #   - id
    #   - role
    #   - osfinger
    #   - os
    #   - os_family
    # All aspects of path/file resolution are customisable using the options below.
    # This is unnecessary in most cases; there are sensible defaults.
    # path_prefix: template_alt
    # dirs:
    #   files: files_alt
    #   default: default_alt
    source_files:
      php_apache2_ini:
        - alt_php.ini
      php_apache2_module_config:
        - alt_mod_php.conf.jinja
      php_cli_ini:      # Used if there is only one version declared
        - alt_php.ini
      php_cli_ini_7.2:  # Used if several versions are declared
        - alt_php.ini
      php_fpm_conf_config:
        - alt_php.ini
      php_fpm_conf_config_7.3:
        - alt_php.ini
      php_fpm_ini_config:
        - alt_php.ini
      php_fpm_ini_config_7.0:
        - alt_php.ini
      php_fpm_pool_conf:
        - alt_php.ini
      php_hhvm_conf_config:
        - alt_php.ini
      php_hhvm_ini_config:
        - alt_php.ini
      php_xcache_ini:
        - alt_php.ini

Steps to reproduce the bug

Expected behaviour

Versions report

Salt Version:
          Salt: 2019.2.0

Dependency Versions:
          cffi: Not Installed
      cherrypy: Not Installed
      dateutil: 2.6.1
     docker-py: Not Installed
         gitdb: 2.0.3
     gitpython: 2.1.8
         ioflo: Not Installed
        Jinja2: 2.10
       libgit2: 0.26.0
       libnacl: Not Installed
      M2Crypto: Not Installed
          Mako: 1.0.7
  msgpack-pure: Not Installed
msgpack-python: 0.5.6
  mysql-python: Not Installed
     pycparser: Not Installed
      pycrypto: 2.6.1
  pycryptodome: Not Installed
        pygit2: 0.26.2
        Python: 2.7.15+ (default, Jul  9 2019, 16:51:35)
  python-gnupg: 0.4.1
        PyYAML: 3.12
         PyZMQ: 16.0.2
          RAET: Not Installed
         smmap: 2.0.3
       timelib: Not Installed
       Tornado: 4.5.3
           ZMQ: 4.2.5System Versions:
          dist: Ubuntu 18.04 bionic
        locale: UTF-8
       machine: x86_64
       release: 5.0.0-1020-azure
        system: Linux
       version: Ubuntu 18.04 bionic

Additional context


Optional: How can this template be improved?

Multiple versions on the same host

Hello,

It seems the "standard" or ng version of this formula doesn't support it, but would it be possible to suport multiple versions of PHP (for instance 7.0 and 7.1) on the same host?

Passed invalid arguments to state.apply: 'NoneType' object is not iterable - on php.ng.fpm.pools

When using salt target state.apply php.ng.fpm.pools with no pillars, we get :

    Passed invalid arguments to state.apply: 'NoneType' object is not iterable

In our case, the php.ng.fpm.pools is included in the top.sls and so no states are applied which is a problem.

    Salt Version:
               Salt: 2017.7.4
     
    Dependency Versions:
               cffi: Not Installed
           cherrypy: Not Installed
           dateutil: 2.5.3
          docker-py: Not Installed
              gitdb: Not Installed
          gitpython: Not Installed
              ioflo: Not Installed
             Jinja2: 2.9.4
            libgit2: Not Installed
            libnacl: Not Installed
           M2Crypto: Not Installed
               Mako: Not Installed
       msgpack-pure: Not Installed
     msgpack-python: 0.4.8
       mysql-python: Not Installed
          pycparser: Not Installed
           pycrypto: 2.6.1
       pycryptodome: Not Installed
             pygit2: Not Installed
             Python: 2.7.13 (default, Nov 24 2017, 17:33:09)
       python-gnupg: Not Installed
             PyYAML: 3.12
              PyZMQ: 16.0.2
               RAET: Not Installed
              smmap: Not Installed
            timelib: Not Installed
            Tornado: 4.4.3
                ZMQ: 4.2.1
     
    System Versions:
               dist: debian 9.4 
             locale: UTF-8
            machine: x86_64
            release: 4.9.0-5-amd64
             system: Linux
            version: debian 9.4 

PHP version 7 on Ubuntu 16.04

I get this error when applying the php.ng.cli and php.ng.apache2 this on Ubuntu 16.04.

    Data failed to compile:
----------
    Rendering SLS 'base:php.ng.cli.ini' failed: Jinja variable 'dict object' has no attribute 'cli'
----------
    Rendering SLS 'base:php.ng.apache2.ini' failed: Jinja variable 'dict object' has no attribute 'apache2'

When setting the following in pillar it works:

php:
  ng:
    version: '7.0'

[BUG] state.apply php.cli, php.fpm and php.xcache fail to compile.

I have found that I am not able to run state.apply "php.cli', 'php.fpm' and 'php.xcache'

Following is a screenshot from the salt master and the response.

I am able to run the commands that they are supposed to run such as php.cli.install and php.cli.ini.

I will include debug log in additional message.

gjohnson@prd-ssm:~$ sudo salt '*work*' state.apply php.xcache
ussc-tst-worker-vm1:
    Data failed to compile:
----------
    Rendering SLS 'base:php.xcache.ini' failed: Jinja variable 'dict object' has no attribute 'defaults'
ERROR: Minions returned with non-zero exit code
gjohnson@prd-ssm:~$ sudo salt '*work*' state.apply php.fpm
ussc-tst-worker-vm1:
    Data failed to compile:
----------
    Rendering SLS 'base:php.fpm' failed: Jinja variable 'dict object' has no attribute 'fpm_pkg'
ERROR: Minions returned with non-zero exit code
gjohnson@prd-ssm:~$ sudo salt '*work*' state.apply php.cli
ussc-tst-worker-vm1:
    Data failed to compile:
----------
    Rendering SLS 'base:php.cli' failed: Jinja variable 'dict object' has no attribute 'cli_pkg'
ERROR: Minions returned with non-zero exit code 

Describe the bug

Setup

Steps to reproduce the bug

Expected behaviour

Versions report

Salt Version:
          Salt: 2019.2.0

Dependency Versions:
          cffi: Not Installed
      cherrypy: Not Installed
      dateutil: 2.6.1
     docker-py: Not Installed
         gitdb: 2.0.3
     gitpython: 2.1.8
         ioflo: Not Installed
        Jinja2: 2.10
       libgit2: 0.26.0
       libnacl: Not Installed
      M2Crypto: Not Installed
          Mako: 1.0.7
  msgpack-pure: Not Installed
msgpack-python: 0.5.6
  mysql-python: Not Installed
     pycparser: Not Installed
      pycrypto: 2.6.1
  pycryptodome: Not Installed
        pygit2: 0.26.2
        Python: 2.7.15+ (default, Jul  9 2019, 16:51:35)
  python-gnupg: 0.4.1
        PyYAML: 3.12
         PyZMQ: 16.0.2
          RAET: Not Installed
         smmap: 2.0.3
       timelib: Not Installed
       Tornado: 4.5.3
           ZMQ: 4.2.5System Versions:
          dist: Ubuntu 18.04 bionic
        locale: UTF-8
       machine: x86_64
       release: 5.0.0-1020-azure
        system: Linux
       version: Ubuntu 18.04 bionic

Additional context

Optional: How can this template be improved?

Packages Update After Adding PPA

I am having an issue when I add in a different PPA in the pillar data to install PHP7.0:

php:
  use_ppa: True
  ppa_name: 'ondrej/php'
  ng:
    version: 7.0
...

The PPA gets added but apt-get update is not run so the php7.0 package isn't found.

I worked around this by adding the update to line 31 of php/ng/installed.jinja:

...
- name: apt-add-repository -y ppa:{{ ppa_name }} && apt-get update
...

I was also looking at lines 36โ€“48 of php/ng/installed.jinja but adding in - refresh_db: True to pkgrepo.managed didn't help.

Is there a method I am overlooking that is in the formula already?

php-fpm reload by default

The usual workflow with php-fpm is to trigger a reload instead of a restart, to gracefully handle for all the processes to terminate before killing and respawning the children.

Should we change the defaults for the php-fpm service to enforce this behavior?

use_ppa does not add proper GPG key

When using use_ppa, no GPG is added for the PPA, therefore any states that need to install a package fail with WARNING: The following packages cannot be authenticated! The only key that is currently present is for hhvm. I got around this by just creating a separate state to add the PPA with the proper keyid:

php56-repo:
  pkgrepo.managed:
    - ppa: ondrej/php5-5.6
    - keyid: E5267A6C
    - keyserver: keyserver.ubuntu.com
`

I don't know why this key isn't being pulled in automatically like it should, or whether the issue is specific to my setup (this is a new Ubuntu 14.04 instance).

Wrong package name for php-xdebug

I just wanted to run this by someone before submitting a pull request to make sure I'm getting this right.

In map.jinja, 'xdebug': 'php' + phpng_version + '-xdebug' is used when it should actually be just php-xdebug. It looks like php7.1-xdebug used to exist separately in the ondrej PPA, but no longer. Now php-xdebug works for 5, 7.0, and 7.1.

This is the case when using the repo for all Ubuntu and Debian versions, or when not using the repo for Ubuntu >= 16.04 and Debian > jessie. As far as I can tell, php7.1-xdebug is no longer used at all.

Debian 9 - Package 'php5' has no installation candidate

The map doesn't account that PHP5 is not in Debian 9 anymore thus this error is produced:

          ID: php
    Function: pkg.installed
        Name: php5
      Result: False
     Comment: Problem encountered installing package(s). Additional info follows:
              
              errors:
                  - Running scope as unit: run-r5900112157714843a8cfd57e485e060b.scope
                    E: Package 'php5' has no installation candidate
     Started: 09:38:29.168245
    Duration: 1633.797 ms

I guess one fix would be to have the map treat Debian 9 separately.

Conflicting ids with the latest release

When I run this formula I got this error :

[DEBUG   ] Rendered data from file: /var/cache/salt/minion/files/base/php/ng/fpm/install.sls:
include:
  - php.ng.deprecated

# -*- coding: utf-8 -*-
# vim: ft=jinja

include:
  - php.ng.deprecated

php_install_fpm:
  pkg.installed:
    - name: fpm
    - pkgs: ["php7.0-fpm"]

[CRITICAL] Rendering SLS 'base:php.ng.fpm.install' failed: while constructing a mapping
  in "<unicode string>", line 1, column 1
found conflicting ID 'include'
  in "<unicode string>", line 11, column 1

My pillars:

php:
  ng:
    version:
      - '7.0'
    modules:
      - curl
      - gd
      - mcrypt
      - mysql

My state states/base/install/php.sls :

{% set roles = salt['config.get']('jbox_server:roles', []) %}

{% if 'php-server' in roles %}
include:
  - php.ng.fpm.install
  - php.ng.fpm.config
  - php.ng.fpm.pools_config
  - php.ng.modules
  - php.ng.fpm.service
{% endif %}

If I quote php.ng.fpm.install and php.ng.fpm.service it works :

{% set roles = salt['config.get']('jbox_server:roles', []) %}

{% if 'php-server' in roles %}
include:
  # - php.ng.fpm.install
  - php.ng.fpm.config
  - php.ng.fpm.pools_config
  - php.ng.modules
  # - php.ng.fpm.service
{% endif %}

php state mention unexistent state

While updating my internal php-formula just mentioned php/init.sls includes php.dotdeb which is not existent here.
I suppose inclusion should be removed or state added:)

Request: Support for disabling modules

The Debian packages automatically enable modules when installed. We should add support to easily disable modules. Particularly xdebug, which I only enable when I actually need it, since it slows down composer, and obviously any production websites. Since I saw "phpenmod" was added with the recent change, we might as well add support phpdismod as well for convenience.

Incorrect order in php-fpm.conf

When doing a state.highstate with the following pillar:

php:
  ng:
    fpm:                                                                                                                                                                                                                                                          
      service:                                                                                                                                                                                                                                                    
        enabled: True                                                                                                                                                                                                                                             
        opts:                                                                                                                                                                                                                                                     
          reload: True                                                                                                                                                                                                                                            
      config:                                                                                                                                                                                                                                                     
        ini:                                                                                                                                                                                                                                                      
          opts:
            recurse: True
          settings:
            PHP:
              engine: 'Off'

        conf:
          opts:
            recurse: True
          settings:
            global:
              pid: /var/run/php5-fpm.pid
              error_log: /var/log/php5-fpm.log
              include: /etc/php5/fpm/pool.d/*.conf

Settings will be outputted like this:

    error_log = /var/log/php5-fpm.log
    include = /etc/php5/fpm/pool.d
    pid = /var/run/php5-fpm.pid 

And will break since include -should- be at the end of the config file

PPA key is not successfully added on Ubuntu

Took me a while to figure this one out!

The code added in #72 is broken. The test command needs a switch like -e or -f otherwise it always returns True, whether or not the file in /etc/apt/source.list.d exists.

This means the workaround to pre-add the repo ( apt-add-repository -y ppa:ondrej/php5-5.6 ) is never executed, meaning the next state (the pkgrepo.managed) fails due to the well-known Unicode bug.

I'll submit a PR with a possible fix shortly.

not working with salt-ssh

Sample sls

php:
  warning_messages:
    v1.0.0:
      mute_critical: true
      mute_upcoming: true
  use_external_repo: true
  external_repo_name: 'ondrej/php'
  version: "7.3"

  modules:
    - cli
    - curl
    - mysql

  use_apache_formula: true

produces the error

[DEBUG   ] Results of YAML rendering:
OrderedDict([(u'php_ppa_php', OrderedDict([(u'pkgrepo.managed', [OrderedDict([(u'ppa', u'ondrej/php')]), OrderedDict([(u'__env__', [OrderedDict([(u'LC_ALL', u'C.UTF-8')])])]), OrderedDict([(u'onlyif', [u'test ! -e /etc/apt/sources.list.d/ondrej-ubuntu-php-xenial.list', u'test ! -e /etc/apt/sources.list.d/ondrej-php-xenial.list'])]), OrderedDict([(u'require_in', [OrderedDict([(u'pkg', u'php_install_php')])])])]), (u'pkg.latest', [OrderedDict([(u'name', u'php')]), OrderedDict([(u'pkgs', [u'php7.3'])]), OrderedDict([(u'refresh', True)]), OrderedDict([(u'onchanges', [OrderedDict([(u'pkgrepo', u'php_ppa_php')])])])])])), (u'php_install_php', OrderedDict([(u'pkg.installed', [OrderedDict([(u'name', u'php')]), OrderedDict([(u'pkgs', [u'php7.3'])])])]))])
[PROFILE ] Time (in seconds) to render '/var/cache/salt/master/files/base/php/init.sls' using 'yaml' renderer: 0.00143599510193
[ERROR   ] TypeError encountered executing state.apply: unhashable type: 'list'
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/salt/client/ssh/__init__.py", line 1180, in run_wfunc
    result = self.wfuncs[self.fun](*self.args, **self.kwargs)
  File "/usr/lib/python2.7/dist-packages/salt/client/ssh/wrapper/state.py", line 522, in apply_
    return highstate(**kwargs)
  File "/usr/lib/python2.7/dist-packages/salt/client/ssh/wrapper/state.py", line 694, in highstate
    opts.get('extra_filerefs', '')
  File "/usr/lib/python2.7/dist-packages/salt/client/ssh/state.py", line 138, in lowstate_file_refs
    if saltenv not in refs:
TypeError: unhashable type: 'list'

[BUG] typo make_dirs vs makedirs in php-formula/php/fpm/config.sls

Describe the bug

While using php-formula I found that directories were not being created and discovered a typo of make_dirs rather than makedirs. I have changed and that now works.

Setup

Steps to reproduce the bug

Expected behaviour

Versions report

As mentioned in #200.

Additional context

Found that I needed to re-arrange the code a bit and create the directory before using managed files. This is also in the same file, there are 2 places where I moved the file.directory block in front of the file.managed section. Following is the updated config.sls:

{#- Manages the php-fpm main ini file #}
{%- set tplroot = tpldir.split('/')[0] %}
{%- from tplroot ~ "/map.jinja" import php with context %}
{%- from tplroot ~ "/ini.jinja" import php_ini %}

{%- set ini_settings = php.ini.defaults %}
{%- for key, value in php.fpm.config.ini.settings.items() %}
  {%- if ini_settings[key] is defined %}
    {%- do ini_settings[key].update(value) %}
  {%- else %}
    {%- do ini_settings.update({key: value}) %}
  {%- endif %}
{%- endfor %}

{%- set pillar_php_version = salt['pillar.get']('php:version', '7.0') %}
{%- if pillar_php_version is iterable and pillar_php_version is not string %}
  {%- for version in pillar_php_version %}
    {%- set conf_settings = odict(php.lookup.fpm.defaults) %}
    {%- set first_version = pillar_php_version[0]|string %}
    {%- set ini = php.lookup.fpm.ini|replace(first_version, version) %}
    {%- set conf = php.lookup.fpm.conf|replace(first_version, version) %}
    {%- set pools = php.lookup.fpm.pools|replace(first_version, version) %}

    {%- for key, value in conf_settings.items() %}
      {%- if value is string %}
        {%- do conf_settings.update({key: value.replace(first_version, version)}) %}
      {%- endif %}
    {%- endfor %}
    {%- do conf_settings.global.update({'pid': '/var/run/php' + version + '-fpm.pid' }) %}
    {%- do conf_settings.global.update({'error_log': '/var/log/php' + version + '-fpm.log' }) %}

{{ pools }}:
    file.directory:
        - name: {{ pools }}
        - user: {{ php.lookup.fpm.user }}
        - group: {{ php.lookup.fpm.group }}
        - file_mode: 755
        - makedirs: True
        
php_fpm_ini_config_{{ version }}:
  {{ php_ini(ini,
             'php_fpm_ini_config_' ~ version,
             php.fpm.config.ini.opts,
             ini_settings
  ) }}

php_fpm_conf_config_{{ version }}:
  {{ php_ini(conf,
             'php_fpm_conf_config_' ~ version,
             php.fpm.config.conf.opts,
             odict(conf_settings)
  ) }}
  {%- endfor %}
{%- else %}

{%- set conf_settings = php.lookup.fpm.defaults %}
{%- do conf_settings.update(php.fpm.config.conf.settings) %}

{{ php.lookup.fpm.pools }}:
    file.directory:
        - name: {{ php.lookup.fpm.pools }}
        - user: {{ php.lookup.fpm.user }}
        - group: {{ php.lookup.fpm.group }}
        - file_mode: 755
        - makedirs: True

php_fpm_ini_config:
  {{ php_ini(php.lookup.fpm.ini,
             'php_fpm_ini_config',
             php.fpm.config.ini.opts,
             ini_settings
  ) }}

php_fpm_conf_config:
  {{ php_ini(php.lookup.fpm.conf,
             'php_fpm_conf_config',
             php.fpm.config.conf.opts,
             conf_settings
  ) }}
{%- endif %}

Optional: How can this template be improved?

php.fpm should not include php

The php.fpm state contains the following ever since #113 was merged:

...

include:
  - php

php-fpm:
  ...

Which includes the following:

...
  pkg.latest:
    - name: {{ php.php_pkg }}
    - refresh: True
...

On Debian jessie this will install the php5 metapackage. Unfortunately the installation of php5 pulls in libapache2-mod-php5 and, conversely, apache2 due to the dependencies defined in those packages:

# apt-cache show php5
Package: php5
...
Depends: libapache2-mod-php5 (>= 5.6.30+dfsg-0+deb8u1~) | libapache2-mod-php5filter (>= 5.6.30+dfsg-0+deb8u1~) | php5-cgi (>= 5.6.30+dfsg-0+deb8u1~) | php5-fpm (>= 5.6.30+dfsg-0+deb8u1~), php5-common (>= 5.6.30+dfsg-0+deb8u1~)

# apt-cache show libapache2-mod-php5
Package: libapache2-mod-php5
...
Depends: libbz2-1.0, libc6 (>= 2.15), libcomerr2 (>= 1.01), libdb5.3, libgssapi-krb5-2 (>= 1.6.dfsg.2), libk5crypto3 (>= 1.6.dfsg.2), libkrb5-3 (>= 1.6.dfsg.2), libonig2 (>= 5.9.5), libpcre3 (>= 1:8.35), libqdbm14 (>= 1.8.74), libssl1.0.0 (>= 1.0.1), libstdc++6 (>= 4.1.1), libxml2 (>= 2.9.0), zlib1g (>= 1:1.1.4), apache2-api-20120211, apache2 (>= 2.4), mime-support, php5-common (= 5.6.30+dfsg-0+deb8u1), php5-cli, php5-json, libmagic1, ucf, tzdata

This renders the php.fpm state rather useless as many users install it when they plan to use nginx or lighttpd. In particular the following dependency of php5 would be satisfied by install php5-fpm:

Depends: libapache2-mod-php5 (>= 5.6.30+dfsg-0+deb8u1~) | php5-fpm (>= 5.6.30+dfsg-0+deb8u1~)

Support installation of php5-cgi

Deploying PHP and lighttpd on Debian is made a bit harder as php5-cgi can not be explicitly installed. If you use this formula to install "php" it will pull in libapache2-mod-php5 and apache2-mpm-prefork.

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.