fnichol / chef-user Goto Github PK
View Code? Open in Web Editor NEWA convenient Chef LWRP to manage user accounts and SSH keys
Home Page: http://fnichol.github.io/chef-user
A convenient Chef LWRP to manage user accounts and SSH keys
Home Page: http://fnichol.github.io/chef-user
I'm in the process of learning Chef, so this probably isn't an error with chef-user
, but I'm hoping someone here can help me out.
I clone this repo into cookbooks
with cd cookbooks && git clone git://github.com/fnichol/chef-user.git
, so now I have a ./cookbooks/chef-user
.
Then I add recipe[user::data_bag]
to my run_list
, so the contents of my run_list
are:
{
"run_list":["recipe[user::data_bag]", "recipe[main]"]
}
Then I add ./data_bags/users/cgenco.json
and put some stuff in it.
Then I try to cook it with knife solo:
$ knife solo cook [email protected]
WARNING: No knife configuration file found
Checking Chef version...
Starting Chef Client, version 11.4.4
Compiling Cookbooks...
[2013-06-12T17:32:49+00:00] ERROR: Running exception handlers
[2013-06-12T17:32:49+00:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated
[2013-06-12T17:32:49+00:00] FATAL: Stacktrace dumped to /tmp/chef-solo/chef-stacktrace.out
[2013-06-12T17:32:49+00:00] FATAL: Chef::Exceptions::CookbookNotFound: Cookbook user not found. If you're loading user from another cookbook, make sure you configure the dependency in your metadata
ERROR: RuntimeError: chef-solo failed. See output above.
What am I doing wrong? D:
Its been over 2 years since 0.3.0 was released but there many fixes made to master HEAD in that time (last change April 29th, 2014). Can you please release the next version of this cookbook? Suggest it should be version 0.4.0 (or maybe even 1.0.0).
I have a users data_bag created and when following instructions to add users in recipes it works great but when I try to run the user::data_bag recipe I am getting the following error:
Cannot find a resource for user_account on centos version 6.6
/var/chef/cache/cookbooks/chef-user/recipes/data_bag.rb:38:in block in from_file' /var/chef/cache/cookbooks/chef-user/recipes/data_bag.rb:34:in
each'
/var/chef/cache/cookbooks/chef-user/recipes/data_bag.rb:34:in `from_file'
/var/chef/cache/cookbooks/chef-user/recipes/data_bag.rb:
31: user_array = data_bag(bag) if user_array.nil? || user_array.empty?
32:
33: # only manage the subset of users defined
34: Array(user_array).each do |i|
35: u = data_bag_item(bag, i.gsub(/[.]/, '-'))
36: username = u['username'] || u['id']
37:
38>> user_account username do
39: %w{comment uid gid home shell password system_user manage_home create_group
40: ssh_keys ssh_keygen non_unique}.each do |attr|
41: send(attr, u[attr]) if u[attr]
42: end
43: action Array(u['action']).map { |a| a.to_sym } if u['action']
44: end
45:
46: unless u['groups'].nil? || u['action'] == 'remove'
47: u['groups'].each do |groupname|
Hello!
Would you mind doing a release of this cookbook to supermarket? Chef-client 12's release means we need a name field in the metadata, and while it's present in master@HEAD, it's not in any currently released version of this cookbook in Supermarket.
Thanks!
Here, the recipe name that actually does something should have apparently been "data_bag".
Can a version number be bumped and uploaded to chef supermarket?
It would be really nice if we could specify what type of key to generate. Not all programs allow a DSA key so having the option to generate a RSA key would be great! Thanks.
Please tag the master branch, the newest tag 3.0 is 11 months old. There are fixes in the current master branch that I need to use and I prefer to use versions rather then sha's in my Berksfile
'solaris2' (at least) should also use '/export/home' as the default home parent folder, while the entries in '/etc/passwd' ideally should use '/home' as parent (due to auto_home).
When defining a group in the json files it must be defined in an array even if there is only one group. For example:
Defining a group like this works:
"groups": ["sysadmin"],
Defining a group like this does not work:
"groups": "sysadmin",
The following error is observed:
NoMethodError
undefined method `each' for "sysadmin":String
Any chance support for whyrun on user_account
could be added, please? Really been relying on whyruns these days for quality assurance. Share the whyrun love!
Is there anything @chef-brigade can do to help out? We're probably going to start using this in our infra, so we want to keep it awesome.
If you need any administrative help, want a slack channel, website, testing infra &c, just let us know. It doesn't need to have the brigade name anywhere on it.
The documentation for user_account has groups
listed (twice!), but it doesn't appear to work. Looking in the resources/ folder, groups is the only attribute not listed.
I have set a password shadow in a users databag, and they have since logged in a changed that password. But not chef resets this back to the original on each run. How can I stop it from doing that, while still allowing the user to change his password?
thx
Home directory is created with mode 2755 which is not always desirable. Can this be moved into a node attribute please? Thanks!
The data_bag recipe incorrectly reads from the node['users']
attribute, but the data bag contents are in the users
array
diff --git a/cookbooks/user/recipes/data_bag.rb b/cookbooks/user/recipes/data_bag.rb
index a2dab5f..87877f5 100644
--- a/cookbooks/user/recipes/data_bag.rb
+++ b/cookbooks/user/recipes/data_bag.rb
@@ -25,7 +25,7 @@ rescue => ex
[]
end
-Array(node['users']).each do |i|
+users.each do |i|
u = data_bag_item(bag, i)
username = u['username'] || u['id']
When I want to create a new user like so:
user_account 'new_user' do
ssh_keys "ssh-rsa ..."
action :create
end
Everything works as planned.
But when I try the following:
user_account 'root' do
ssh_keys "ssh-rsa ..."
action :modify
end
I get the following error:
Error executing action modify
on resource 'user_account[root]'
user[root](/var/chef/cache/cookbooks/user/providers/account.rb line 94) had an error: Chef::Exceptions::Exec: usermod -m -d '/home/root' root returned 8, expected 0
/var/chef/cache/cookbooks/user/providers/account.rb:105:in user_resource' /var/chef/cache/cookbooks/user/providers/account.rb:46:in
block in class_from_file'
In /var/chef/cache/cookbooks/rollcall/recipes/default.rb
13: user_account 'root' do
14: ssh_keys "ssh-rsa ..."
15: action :modify
16: end
17:
Declared in /var/chef/cache/cookbooks/rollcall/recipes/default.rb:13:in `from_file'
user_account("root") do
action [:modify]
retries 0
retry_delay 2
cookbook_name "rollcall"
recipe_name "default"
ssh_keys "ssh-rsa ..."
username "root"
end
Any idea what I'm doing wrong?
Thanks,
Nicolas
hello, as it is written in USAGE section i added recipe[user::data_bag] into run list:
knife node show chef-test-client
Node Name: chef-test-client
Environment: _default
FQDN: chef-test-client
IP: 192.168.16.777
Run List: recipe[user::data_bag]
Roles:
Recipes: user::data_bag
Platform: debian 7.1
here is my data bag:
and my data bag:
knife data bag show users user
groups: sudo
home: /home/user
id: user
password: >$6$wkWXnXUk$xjaISNyG3cDGU2X
shell: /bin/bash
uid: 1002
and after executing chef-client on client node, nothing happens, user is not created; what am i doing wrong ?, guys please help me to deal with it
The attribute password is not working on macOS:
user_account 'bob' do
password '$1$tiuw.sv......WrKU37APys00'
ssh_keys ['ssh-rsa AAAAB3NzaC1yc2EAAAADAQA...']
end
The same recipe works on Debian, password correctly created for Debian 8.8 user.
macOS Sierra 10.12.5
Chef 12.17.44 and 13.0.118
chef-user 0.7.0
Thanks
The error message is:
STDERR: usermod: user jenkins is currently logged in
I only need to add private keys to the user. Is it possible to protect so the user resource so that would be possible?
How do I suppose to add a user inside my node/my.site.json file? I've already tried:
{
"users": [
{
"username": "juliobetta",
"password": "mypass",
"groups": ["admin", "www-data"]
}
],
"run_list" : [
"recipe[user]", "recipe[user::data_bag]"
]
}
And then when I try to knife solo cook [email protected]
it says that:
ERROR: Undefined node attribute or method `gsub' on `node'
Hi !
How do you manage the groups ? would it be hard to extend this cookbook to add a "groups" attribute in the user data bag ?
If I add
"action": "remove"
to a user's data bag item, the first chef-client run will remove the user--but the second will raise an exception:
ArgumentError: user_account[notanymore] (user::data_bag line 27) had an error: ArgumentError: can't find user for notanymore
Shouldn't remove
handle the case where the user's already been removed? Or is there a better way?
Hey Fletcher, any reason not to install this, since user passwords rely on it? At least for the data_bag recipe, maybe only if a password entry is given for a user, then have the recipe do it? Let me know your thoughts, and I can submit a pull request
Using the user::data_bag
recipe, I seem to need to provide "false" as a string; as a boolean, it's ignored. Possibly related to #9?
I have created a user in vagrant image, simply as
user_account "deploy" do
comment "deployer"
ssh_keys ["3dc348d9af8027df7b9c...", "2154d3734d609eb5c452..."]
home "/home/deploy"
shell "/bin/bash"
end
but the problem is that when I do sudo su deploy
, he doesn't source scripts from /etc/profile.d/*
, even though he has the rights to do it, and the vagrant
user does it by default.
Is there something else that I need to do? I'm doing this on ubuntu 10.04
user_account node['current_user'] do
password node[:new_password]
action :modify
end
Expected behaviour: Changes the user's password, leaving everything else intact.
Observed behaviour: Overwrites authorized_keys
file, creates new SSH keys, then runs away laughing.
Should this be unless exec_action == :remove ?
https://github.com/fnichol/chef-user/blob/master/providers/account.rb#L107
Just realized that the user cookbook breaks in ruby 1.8.6 due to this line:
https://github.com/fnichol/chef-user/blob/master/providers/account.rb#L115
I've been trying to take advantage of the data_bags recipe but wasn't able to get it to work. I'm provisioning a vm using vagrant and hosted chef.
I may not be able to get it to work because I'm not understanding how it is suppose to work but following the data bags page from the opscode wiki (http://wiki.opscode.com/display/chef/Data+Bags) I was able to change the data_bags recipe to the following and then it worked.
# data_bag.rb
users = data_bag("users")
users.each do |i|
u = data_bag_item("users", i.gsub(/[.]/, '-'))
username = u['username'] || u['id']
user_account username do
%w{comment uid gid home shell password system_user manage_home create_group
ssh_keys ssh_keygen}.each do |attr|
send(attr, u[attr]) if u[attr]
end
action u['action'].to_sym if u['action']
end
end
Obviously this specifies the users data bag which I think you were trying to avoid. I may just not understand how I'm suppose to specify the data bag using the original code. Thoughts on what my problem? I just need some more direction here.
Here is what my data bag looks like
data_bags/
|---users/
|--- deployuser.json
deployer.json is below
{
"id" : "deployer",
"comment" : "Deploy User",
"ssh_keys" : "ssh-rsa AAAAB3N..."
}
In my opinion, after a user was created, ohai should be notified to reload passwd data, so ohai attributes for that user can be used in other recipes.
I'm not sure whether this should be added to the user creation itself as described here or at the end of the users::databag recipe (so creating 100 users would only trigger 1 reload).
Seems there are some outstanding issues that could do with a release:
#82
Please and thanks! :)
So I built my cookbook using kitchen and it's passes all tests and the users are created.
If I pull my cookbook in as a Berkshelf dependency and launch a provision instruction via vagrant up --provision
, I'm getting the following error:
ERROR: Failed to load data bag item: "users" "deploy"
Here is my deploy data bag (accessible via my-cookbook/data_bags/users/deploy.json):
{
"id": "deploy",
"comment": "Deploy User",
"home": "/home/deploy",
"groups": ["deploy"],
"ssh_keys": ["ssh-rsa 12345 [email protected]", "ssh-rsa 12345 [email protected]"],
"action": "create"
}
When building through vagrant, is there something specific I need to do to get this working?
Per #42, #73, #74, all four resources are touched no matter what you're actually changing. For example, for this action:
action :modify do
user_resource :modify
dir_resource :create
authorized_keys_resource :create
keygen_resource :create
end
There's basically no one way to user_resource
, dir_resource
, authorized_keys_resource
, or keygen_resource
independently. Thus, modifying any of them ends up modifying all of them. This especially unpleasant with .authorized_keys
as doing anything to a user wipes the file, even if you're performing an unrelated operation.
Just wanted to type this out so I don't forget, so if you're busy, I'll send a pull request when I get a sec
Right now home
is a combination of home_root
and username
. It would be nice to separate those so we can pass in our own home_root
with the resource.
Example:
user_account "zeus" do
home_root "/var/lib"
ssh_keygen false
action [:create, :manage]
end
I was hoping to be able to the user and group with specific ids:
user_account "testuser" do
comment "Test User"
uid 9999
gid 9999
create_group true
ssh_keygen false
end
but this fails with:
[2012-09-28T23:25:59+00:00] DEBUG: Chef::Exceptions::Exec: user_account[testuser] (dummy-service::default line 10) had an error: Chef::Exceptions::Exec: user[testuser] (/tmp/vagrant-chef-1/chef-solo-1/cookbooks/user/providers/account.rb line 94) had an error: Chef::Exceptions::Exec: useradd -c 'Test User' -g '9999' -s '/bin/bash' -u '9999' -m -d '/home/testuser' testuser returned 6, expected 0
---- Begin output of useradd -c 'Test User' -g '9999' -s '/bin/bash' -u '9999' -m -d '/home/testuser' testuser ----
STDOUT: STDERR: useradd: group '9999' does not exist
---- End output of useradd -c 'Test User' -g '9999' -s '/bin/bash' -u '9999' -m -d '/home/testuser' testuser ----
[2012-11-01T03:02:10+00:00] INFO: Storing updated cookbooks/user/attributes/default.rb in the cache.
string not matched
/var/chef/cache/cookbooks/user/attributes/default.rb:24:in []=' /var/chef/cache/cookbooks/user/attributes/default.rb:24:in
from_file'
/var/chef/cache/cookbooks/user/attributes/default.rb:
19: # limitations under the License.
20: #
21:
22: case platform
23: when 'debian','ubuntu','redhat','centos','amazon','scientific','fedora','freebsd','suse'
24>> default['user']['home_root'] = "/home"
25: default['user']['default_shell'] = "/bin/bash"
26: when 'openbsd'
27: default['user']['home_root'] = "/home"
28: default['user']['default_shell'] = "/bin/ksh"
29: when 'mac_os_x', 'mac_os_x_server'
30: default['user']['home_root'] = "/Users"
31: default['user']['default_shell'] = "/bin/bash"
32: else
33: default['user']['home_root'] = "/home"
[2012-11-01T03:02:10+00:00] ERROR: Running exception handlers
[2012-11-01T03:02:10+00:00] FATAL: Saving node information to /var/chef/cache/failed-run-data.json
[2012-11-01T03:02:10+00:00] ERROR: Exception handlers complete
[2012-11-01T03:02:10+00:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
[2012-11-01T03:02:10+00:00] FATAL: IndexError: string not matched
If you have an apostrophe in the comment it produces an invalid command.
For example:
useradd -c 'John Smith's Account' ...
The above command now has an open quote.
This MAY be related to issue #95 . If so, I'll close this as a duplicate.
My cookbook setup is as follows:
If I converge a test kitchen node for ap-ops, it claims undefined method 'groups' for Chef::Resource::UserAccount
.
================================================================================
Recipe Compile Error in /tmp/kitchen/cache/cookbooks/ap-ops/recipes/default.rb
================================================================================
NoMethodError
-------------
undefined method `groups' for Chef::Resource::UserAccount
Cookbook Trace:
---------------
/tmp/kitchen/cache/cookbooks/ap-baseline/recipes/config_ssh.rb:34:in `block (2 levels) in from_file'
/tmp/kitchen/cache/cookbooks/ap-baseline/recipes/config_ssh.rb:30:in `block in from_file'
/tmp/kitchen/cache/cookbooks/ap-baseline/recipes/config_ssh.rb:27:in `each'
/tmp/kitchen/cache/cookbooks/ap-baseline/recipes/config_ssh.rb:27:in `from_file'
/tmp/kitchen/cache/cookbooks/ap-baseline/recipes/default.rb:26:in `from_file'
/tmp/kitchen/cache/cookbooks/ap-ops/recipes/default.rb:7:in `from_file'
Relevant File Content:
----------------------
/tmp/kitchen/cache/cookbooks/ap-baseline/recipes/config_ssh.rb:
27: node['allowed_users'].each do |uname|
28: @@ssh_key = Vault.logical.read("secret/eng/#{uname}").data[:ssh_key]
29:
30: user_account uname do
31: action :create
32: home "/home/#{uname}"
33: shell '/bin/bash'
34>> groups ['sysadmin']
35: ssh_keygen false
36: ssh_keys @@ssh_key
37: end
38:
39: @@all_keys << @@ssh_key
40: end
41:
42: user_account 'anyperk' do
43: action :modify
Running handlers:
Running handlers complete
Chef Client failed. 0 resources updated in 2.938709548 seconds
[2015-11-11T11:07:17-08:00] ERROR: undefined method `groups' for Chef::Resource::UserAccount
[2015-11-11T11:07:17-08:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
However, if I explicitly include the user cookbook in the ap-ops cookbook (via Berkshelf and the metadata.rb file), the converge finishes successfully. Is this by design? I was under the impression I only need to include the user cookbook dependency where the LWRP is used (in the ap-baseline cookbook).
Vagrant setup:
config.vm.define "nginx" do |nginx|
nginx.vm.box = "hashicorp/precise64"
nginx.vm.network "private_network", ip: "192.168.33.110"
nginx.vm.provision "chef_zero" do |chef|
chef.cookbooks_path = ["cookbooks", "site-cookbooks"]
chef.install = false
# chef.add_recipe "nginx"
end
end
Error message
==> nginx: ================================================================================
==> nginx: Recipe Compile Error in /tmp/vagrant-chef/375f1ae162902bb20345a95ec67bb151/cookbooks/user/providers/account.rb
==> nginx: ================================================================================
==> nginx:
==> nginx: NameError
==> nginx: ---------
==> nginx: undefined local variable or method `use_inline_resources' for #<Class:0x7f0d9b9ad508>
==> nginx:
==> nginx: Cookbook Trace:
==> nginx: ---------------
==> nginx: /tmp/vagrant-chef/375f1ae162902bb20345a95ec67bb151/cookbooks/user/providers/account.rb:23:in `class_from_file'
I have data_bags/users/cyrus.json
with the following:
{
"id": "cyrus",
"ssh_keys":[
"ssh-rsa ..."
],
"password": "foobar"
}
Yet when I run chef:
[2014-04-14T20:51:06+08:00] WARN: Overridden Run List: [recipe[user::data_bag]]
Compiling Cookbooks...
Converging 0 resources
Running handlers:
Running handlers complete
Chef Client finished, 0/0 resources updated in 1.640126988 seconds
nothing happened. What have I missed?
I'm trying to add authorized_keys to a user (the root user) but not modify anything else.
I therefore have manage_home set to false...
"manage_home": "false",
However, despite this it's still executing usermod with parameters '-d /home/root'
[Fri, 08 Jun 2012 14:32:32 +0100] INFO: Processing user[root] action manage (/var/chef/cache/cookbooks/user/providers/account.rb line 94)
[Fri, 08 Jun 2012 14:32:32 +0100] DEBUG: user[root] setting home to /home/root
[Fri, 08 Jun 2012 14:32:32 +0100] DEBUG: Executing usermod -d '/home/root' root
[Fri, 08 Jun 2012 14:32:32 +0100] DEBUG: ---- Begin output of usermod -d '/home/root' root ----
[Fri, 08 Jun 2012 14:32:32 +0100] DEBUG: STDOUT:
[Fri, 08 Jun 2012 14:32:32 +0100] DEBUG: STDERR: usermod: user root is currently logged in
[Fri, 08 Jun 2012 14:32:32 +0100] DEBUG: ---- End output of usermod -d '/home/root' root ----
[Fri, 08 Jun 2012 14:32:32 +0100] DEBUG: Ran usermod -d '/home/root' root returned 8
I'm not sure if this is a bit in the useradd provider of chef, or the user cookbook. Certainly if manage_home is being set to false when setting up the user resource in account.rb:102 then useradd.rb should be realising this and not passing the flag.
I'm rather new to Chef, but having traced this back as far as I can, it does seem like the chef user provider isn't working as it should. I wanted to get your thoughts on this.
Thanks
A
user_account 'xxx' do
action :remove
end
brings error in knife solo cook
Error executing action remove
on resource 'user_account[xxx]'
A pattern that might be followed in a cookbook is:
node.default['users'] << 'exampleuser'
include_recipe 'user::data_bag'
However if a run_list includes multiple cookbooks (and it usually does) and more than one cookbook tries that pattern, it will fail. Because you can not include_recipe twice.
So, node.default['users'] = ['exampleuser', 'exampleuser2'] has to be set somewhere else, outside the cookbook as an extra step, such as on a role or node.
Or, have user_account directly:
user_account 'hsolo' do
ssh_keygen true
end
Then the data is not in a data_bag, it must be directly in the cookbook.
It would be nice if user_account could load data from a data_bag, or if a new lwrp loaded a user_account from a databag. or you could include_recipe twice.
what is the easiest way to handle this case?
Is there any way using this cookbook to set password expiry options?
Typically:
root@someserver:~# chage -l root
Last password change: Mar 24, 2017
Password expires: never
Password inactive: never
Account expires: never
Minimum number of days between password change: 0
Maximum number of days between password change: 99999
Number of days of warning before password expires: 7
Doesn't seem to work anyway:
Chef::Exceptions::ValidationFailed
----------------------------------
Option comment must be a kind of String! You passed {"encrypted_data"=>"CqvxeieeVoHvx98kgglg06hsqnx2mN/wp9u1gCaPfERnL218h4hraMyF+qKl\n4sNf\n", "iv"=>"CcVBWx/mLmaJUrxjARS3Bw==\n", "version"=>1, "cipher"=>"aes-256-cbc"}.
Cookbook Trace:
---------------
/home/vagrant/chef-solo/cookbooks-2/user/recipes/data_bag.rb:39:in `block (3 levels) in from_file'
/home/vagrant/chef-solo/cookbooks-2/user/recipes/data_bag.rb:37:in `each'
/home/vagrant/chef-solo/cookbooks-2/user/recipes/data_bag.rb:37:in `block (2 levels) in from_file'
/home/vagrant/chef-solo/cookbooks-2/user/recipes/data_bag.rb:36:in `block in from_file'
/home/vagrant/chef-solo/cookbooks-2/user/recipes/data_bag.rb:32:in `each'
/home/vagrant/chef-solo/cookbooks-2/user/recipes/data_bag.rb:32:in `from_file'
Action create fails with EnclosingDirectoryDoesNotExist when ssh_keypair exists and ssh_keys empty:
Chef::Exceptions::EnclosingDirectoryDoesNotExist
------------------------------------------------
file[/Users/dummy/.ssh/id_rsa.pub] (/tmp/kitchen/cache/cookbooks/user/providers/account.rb line 269) had an error: Chef::Exceptions::EnclosingDirectoryDoesNotExist: Parent directory /Users/dummy/.ssh does not exist.
home_ssh_dir_resource must run if ssh_keypair is set.
I see how this value can be set in the data bag and I also see how there is a default value set in the attributes (i.e. default['user']['create_user_group']
), but I never see it being used.
Inside the account provider, I see this line:
@create_group = bool(new_resource.create_group, node['user']['create_group'])
but I never see this value used anywhere in the rest of the file.
Am I missing something here? I would think that if this option is passed, then the gid should be set to "users" or something similar.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.