marcinbojko / hv-packer Goto Github PK
View Code? Open in Web Editor NEWHyper-V Generation 2 Packer Templates for Windows 2019/2022, AlmaLinux 8.x/AlmaLinux 9.x/RockyLinux 8.x/9.x/OracleLinux 8.x/9.x Ubuntu 20.04/Ubuntu 22.04/Ubuntu 24.04
Hyper-V Generation 2 Packer Templates for Windows 2019/2022, AlmaLinux 8.x/AlmaLinux 9.x/RockyLinux 8.x/9.x/OracleLinux 8.x/9.x Ubuntu 20.04/Ubuntu 22.04/Ubuntu 24.04
Hello.
Trying to run centos 7.8 on the Windows Server 2019 Hyper V and getting dracut-initqueue timeout - starting timeout scripts
error.
Not sure if it's similar to #4
Hi @marcinbojko ,
I wanted to confirm from your end on the use of ansible remote or local provisioner with Packer when we run packer in hyper-v and the image which is getting build is also Windows.
I believe this can't be done as both the source(Hyper-V) and image getting build are windows machine and ansible can't be install on it. But can u confirm if their is any alternative to get this done?
vagrant/hv_win2022_dc.template contains an incorrect setting to define a ws22dc setup.
config.vm.define "vagrant-w2k19-dc-trial" should be w2k22-dc
config.vm.box = "w2k19-dc-trial" should be w2k22-dc
Unless I'm completely off-base here and missing something.
Otherwise, love your work. Hyper-V is a godsend compared to dealing with VMware licensing terms + pricing
hi , i am getting error "dracut-initqueue : warning cloud not boot" have you come across similar issue ? if yes how did you fix it?
Hi,
could you document how much disk space you allocated for the (gitlab-)CI builds?
I just know my normal builder will never fit all those images, but don't know how big the new one should become ;-)
Have you considered integrating Packer Windows Update Provisioner into your provision steps? The output of this plugin is much cleaner when ran via PowerShell vs raw output of the WU com object with PSWindowsupdate.
I'll be testing this against Windows Server 2019 DC and will report back if there are any issues.
Love the work you've done so far! Having come from a VMware shop to HyperV shop has been challenging, but your code has helped tremendously!
I get the warning below. But I run the script from the root of the repository, what source code is not available?
Building: Ubuntu 22.04
Warning: Hyper-V might fail to create a VM if there is not enough free memory in the system.
on ./templates/hv_ubuntu2204_g2.pkr.hcl line 95:
(source code not available)
The configuration is valid.
1.9.4
Windows 11
boot_command=["<wait3>c<wait3>","linux /casper/vmlinuz quiet autoinstall net.ifnames=0 biosdevname=0 ip=dhcp ipv6.disable=1 ds=nocloud-net\\;s=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ <enter>","initrd /casper/initrd <enter>","boot <enter>"]
disk_additional_size=["150000"]
disk_size="70000"
http_directory="./extra/files/ubuntu/22.04/hyperv"
iso_checksum_type="sha256"
iso_checksum="a4acfda10b18da50e2ec50ccaf860d7f20b389df8765611142305c0e911d16fd"
iso_url="https://releases.ubuntu.com/jammy/ubuntu-22.04.3-live-server-amd64.iso"
output_directory="output-ubuntu2204"
#output_vagrant="./vbox/packer-ubuntu2204-g2.box"
provision_script_options="-z false -h true -p false"
ssh_password="password"
ssh_username="ubuntu"
switch_name="Default Switch"
#vagrantfile_template="./vagrant/hv_ubuntu2204_g2.template"
vlan_id=""
vm_name="packer-ubuntu2204-g2"
uefi_file="extra/files/ubuntu/22.04/uefi.sh"
provision_file="extra/files/ubuntu/shared/provision.sh"
motd_file="extra/files/ubuntu/shared/motd.sh"
zeroing_file="extra/files/ubuntu/shared/zeroing.sh"
neofetch_file="extra/files/ubuntu/shared/prepare_neofetch.sh"
variable "ansible_override" {
type = string
default = ""
}
variable "boot_command" {
}
variable "disk_size" {
type = string
default = "70000"
}
variable "disk_additional_size" {
type = list(number)
default = ["1024"]
}
variable "memory" {
type = string
default = "1024"
}
variable "cpus" {
type = string
default = "1"
}
variable "iso_checksum" {
type = string
default = ""
}
variable "iso_checksum_type" {
type = string
default = "none"
}
variable "iso_url" {
type = string
default = ""
}
variable "output_directory" {
type = string
default = ""
}
variable "provision_script_options" {
type = string
default = ""
}
variable "output_vagrant" {
type = string
default = ""
}
variable "ssh_password" {
type = string
default = ""
sensitive = true
}
variable "switch_name" {
type = string
default = ""
}
variable "vagrantfile_template" {
type = string
default = ""
}
variable "vlan_id" {
type = string
default = ""
}
variable "vm_name" {
type = string
default = ""
}
variable "http_directory" {
type = string
default = ""
}
variable "ssh_username" {
type = string
default = "ubuntu"
}
variable "uefi_file" {
type = string
default = ""
}
variable "provision_file" {
type = string
default = ""
}
variable "motd_file" {
type = string
default = ""
}
variable "neofetch_file" {
type = string
default = ""
}
variable "zeroing_file" {
type = string
default = ""
}
source "hyperv-iso" "vm" {
boot_command = "${var.boot_command}"
boot_wait = "1s"
communicator = "ssh"
cpus = "${var.cpus}"
disk_block_size = "1"
disk_size = "${var.disk_size}"
enable_dynamic_memory = "true"
enable_secure_boot = false
generation = 2
guest_additions_mode = "disable"
http_directory = "${var.http_directory}"
iso_checksum = "${var.iso_checksum_type}:${var.iso_checksum}"
iso_url = "${var.iso_url}"
memory = "${var.memory}"
output_directory = "${var.output_directory}"
shutdown_command = "echo 'password' | sudo -S shutdown -P now"
shutdown_timeout = "30m"
ssh_password = "${var.ssh_password}"
ssh_timeout = "4h"
ssh_username = "${var.ssh_username}"
switch_name = "${var.switch_name}"
temp_path = "."
vlan_id = "${var.vlan_id}"
vm_name = "${var.vm_name}"
}
build {
sources = ["source.hyperv-iso.vm"]
provisioner "file" {
destination = "/tmp/uefi.sh"
source = "${var.uefi_file}"
}
provisioner "file" {
destination = "/tmp/provision.sh"
source = "${var.provision_file}"
}
provisioner "file" {
destination = "/tmp/scvmmguestagent.1.0.3.1028.x64.tar"
source = "extra/files/scagent/1.0.3.1028/scvmmguestagent.1.0.3.1028.x64.tar"
}
provisioner "file" {
destination = "/tmp/install"
source = "extra/files/scagent/1.0.3.1028/install.sh"
}
provisioner "shell" {
execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'"
expect_disconnect = true
inline = ["chmod +x /tmp/provision.sh", "chmod +x /tmp/uefi.sh", "mv /tmp/uefi.sh /usr/local/bin/uefi.sh", "/tmp/provision.sh ${var.provision_script_options}", "sync;sync;reboot"]
inline_shebang = "/bin/sh -x"
}
provisioner "file" {
destination = "/tmp/motd.sh"
source = "${var.motd_file}"
}
provisioner "file" {
destination = "/tmp/prepare_neofetch.sh"
source = "${var.neofetch_file}"
}
provisioner "file" {
destination = "/tmp/zeroing.sh"
source = "${var.zeroing_file}"
}
provisioner "shell" {
execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'"
inline = ["echo Last Phase",
"chmod +x /tmp/prepare_neofetch.sh",
"chmod +x /usr/local/bin/uefi.sh",
"chmod +x /tmp/zeroing.sh",
"/tmp/prepare_neofetch.sh",
"/tmp/zeroing.sh",
"/bin/rm -rfv /tmp/*",
"/bin/rm -f /etc/ssh/*key*",
"/usr/bin/ssh-keygen -A",
"echo 'packerVersion: ${packer.version}' >>/etc/packerinfo"]
inline_shebang = "/bin/sh -x"
}
}
From what I can tell, it crashes after the provisioning script is completed and right before it places the motd.sh
file into the tmp
folder. Could you please let me know where I might be going wrong with this? I tried running this using the powershell script you have provided as well as just running the packer command. The results are the same.
Here is my repo: https://github.com/tinntvs/packer
Could you help me to check the issues?
Thanks!
Hi, I am trying to auto-install the ubuntu22.04 live server with packer hyperv-iso builder.
A few times it worked without any issues and now suddenly it stopped working and it is not taking the kickstart file and popping GUI to select the language. When Packer starts It automatically serves HTTP and after that, I checked in the browser with IP:PORT I can see the user-data and meta-data files present. I don't know what went wrong. Can you please help me here?
packer version 1.9.4
Operating system and Environment details
Windows 10
The variables file :
boot_command=["c<wait>","linux /casper/vmlinuz --- autoinstall ds=\"nocloud-net;seedfrom=http://{{.HTTPIP}}:{{.HTTPPort}}/\"","<enter><wait>","initrd /casper/initrd","<enter><wait>","boot","<enter>"]
disk_additional_size=["150000"]
disk_size="70000"
http_directory="cidata"
iso_checksum_type="sha256"
iso_checksum="a4acfda10b18da50e2ec50ccaf860d7f20b389df8765611142305c0e911d16fd"
iso_url="https://releases.ubuntu.com/jammy/ubuntu-22.04.3-live-server-amd64.iso"
output_directory="output-ubuntu2204"
#output_vagrant="./vbox/packer-ubuntu2204-g2.box"
provision_script_options="-z false -h true -p false"
ssh_password="ubuntu"
ssh_username="ubuntu"
switch_name="packer-hyperv-iso"
#vagrantfile_template="./vagrant/hv_ubuntu2204_g2.template"
vlan_id=""
vm_name="packer-ubuntu2204-g2"
uefi_file="./Boot-scripts/uefi.sh"
provision_file="./Boot-scripts/provision.sh"
motd_file="./Boot-scripts/motd.sh"
zeroing_file="./Boot-scripts/zeroing.sh"
neofetch_file="./Boot-scripts/prepare_neofetch.sh"
Template file:
variable "ansible_override" {
type = string
default = ""
}
variable "boot_command" {
}
variable "disk_size" {
type = string
default = "70000"
}
variable "disk_additional_size" {
type = list(number)
default = ["1024"]
}
variable "memory" {
type = string
default = "1024"
}
variable "cpus" {
type = string
default = "1"
}
variable "iso_checksum" {
type = string
default = ""
}
variable "iso_checksum_type" {
type = string
default = "none"
}
variable "iso_url" {
type = string
default = ""
}
variable "output_directory" {
type = string
default = ""
}
variable "provision_script_options" {
type = string
default = ""
}
variable "output_vagrant" {
type = string
default = ""
}
variable "ssh_password" {
type = string
default = ""
sensitive = true
}
variable "switch_name" {
type = string
default = ""
}
variable "vagrantfile_template" {
type = string
default = ""
}
variable "vlan_id" {
type = string
default = ""
}
variable "vm_name" {
type = string
default = ""
}
variable "http_directory" {
type = string
default = ""
}
variable "ssh_username" {
type = string
default = "ubuntu"
}
variable "uefi_file" {
type = string
default = ""
}
variable "provision_file" {
type = string
default = ""
}
variable "motd_file" {
type = string
default = ""
}
variable "neofetch_file" {
type = string
default = ""
}
variable "zeroing_file" {
type = string
default = ""
}
source "hyperv-iso" "vm" {
boot_command = "${var.boot_command}"
boot_wait = "1s"
communicator = "ssh"
cpus = "${var.cpus}"
disk_block_size = "1"
disk_size = "${var.disk_size}"
enable_dynamic_memory = "true"
enable_secure_boot = false
generation = 2
guest_additions_mode = "disable"
http_directory = "${var.http_directory}"
iso_checksum = "${var.iso_checksum_type}:${var.iso_checksum}"
iso_url = "${var.iso_url}"
memory = "${var.memory}"
output_directory = "${var.output_directory}"
shutdown_command = "echo 'ubuntu' | sudo -S shutdown -P now"
shutdown_timeout = "30m"
ssh_password = "${var.ssh_password}"
ssh_timeout = "4h"
ssh_username = "${var.ssh_username}"
switch_name = "${var.switch_name}"
temp_path = "."
vlan_id = "${var.vlan_id}"
vm_name = "${var.vm_name}"
}
build {
sources = ["source.hyperv-iso.vm"]
provisioner "file" {
destination = "/tmp/uefi.sh"
source = "${var.uefi_file}"
}
provisioner "file" {
destination = "/tmp/provision.sh"
source = "${var.provision_file}"
}
provisioner "file" {
destination = "/tmp/scvmmguestagent.1.0.3.1028.x64.tar"
source = "./Boot-scripts/scvmmguestagent.1.0.3.1028.x64.tar"
}
provisioner "file" {
destination = "/tmp/install"
source = "./Boot-scripts/install.sh"
}
provisioner "shell" {
execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'"
expect_disconnect = true
inline = ["chmod +x /tmp/provision.sh", "chmod +x /tmp/uefi.sh", "mv /tmp/uefi.sh /usr/local/bin/uefi.sh", "/tmp/provision.sh ${var.provision_script_options}", "sync;sync;reboot"]
inline_shebang = "/bin/sh -x"
}
provisioner "file" {
destination = "/tmp/motd.sh"
source = "${var.motd_file}"
}
provisioner "file" {
destination = "/tmp/prepare_neofetch.sh"
source = "${var.neofetch_file}"
}
provisioner "file" {
destination = "/tmp/zeroing.sh"
source = "${var.zeroing_file}"
}
provisioner "shell" {
execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'"
inline = ["echo Last Phase",
"chmod +x /tmp/prepare_neofetch.sh",
"chmod +x /usr/local/bin/uefi.sh",
"chmod +x /tmp/zeroing.sh",
"/tmp/prepare_neofetch.sh",
"/tmp/zeroing.sh",
"/bin/rm -rfv /tmp/*",
"/bin/rm -f /etc/ssh/*key*",
"/usr/bin/ssh-keygen -A",
"echo 'packerVersion: ${packer.version}' >>/etc/packerinfo"]
inline_shebang = "/bin/sh -x"
}
provisioner "shell" {
execute_command = "echo '${var.ssh_password}' | {{.Vars}} sudo -S -E bash '{{.Path}}'"
script = "./Shell-Scripts/azure.sh"
}
provisioner "shell" {
execute_command = "echo '${var.ssh_password}' | {{.Vars}} sudo -S -E bash '{{.Path}}'"
script = "./Shell-Scripts/cleanup.sh"
}
}
Kickstart/cloud-init file:
#cloud-config
autoinstall:
version: 1
indentity:
hostname: ubuntu2204
password: $6$rounds=4096$JFVw4zdHh/ahPcjO$NFG4XVjVbcB7kX9KR7nf9zSXTHZnfVqztfC3wPQJbR6tLkFmxEEKuk7lr8Kp6p7z6cdb9qsqINnEtteJYk5h21
username: ubuntu
early-commands:
- systemctl stop ssh # otherwise packer tries to connect and exceed max attempts
network:
network:
version: 2
ethernets:
eth0:
dhcp4: yes
dhcp-identifier: mac
update: no
apt:
geoip: true
preserve_sources_list: false
primary:
- arches: [amd64]
uri: "http://archive.ubuntu.com/ubuntu/"
packages:
- mc
- curl
- wget
- sudo
- tar
- bzip2
- build-essential
- linux-image-virtual
- linux-tools-virtual
# - linux-cloud-tools-virtual
- net-tools
- qemu-guest-agent
locale: en_US.UTF-8
timezone: Europe/Copenhagen
ssh:
install-server: true
allow-pw: true
user-data:
disable_root: false
lock-passwd: false
ssh_pwauth: true
hostname: ubuntu2204
password: $6$rounds=4096$JFVw4zdHh/ahPcjO$NFG4XVjVbcB7kX9KR7nf9zSXTHZnfVqztfC3wPQJbR6tLkFmxEEKuk7lr8Kp6p7z6cdb9qsqINnEtteJYk5h21
username: ubuntu
late-commands:
#- echo 'ubuntu ALL=(ALL) NOPASSWD:ALL' > /target/etc/sudoers.d/ubuntu
- sed -ie 's/GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="net.ifnames=0 ipv6.disable=1 biosdevname=0 elevator=noop"/' /target/etc/default/grub
- sed -ie 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /target/etc/ssh/sshd_config
- sed -ie 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /target/etc/ssh/sshd_config
- sed -ie 's/#AllowAgentForwarding yes/AllowAgentForwarding yes/' /target/etc/ssh/sshd_config
- curtin in-target -- update-grub2
# virtual package is required for some cloud images. Lack of it causes failure in communication.
- curtin in-target -- apt-get -y install linux-cloud-tools-virtual||true
- curtin in-target -- systemctl enable qemu-guest-agent
storage:
config:
- type: disk
id: disk0
ptable: gpt
wipe: superblock
grub_device: true
match:
size: largest
- id: efi-partition # create partitions on disk (like sda1)
type: partition
device: disk0
size: 512MB
flag: boot # EFI system partition needs boot flag
- type: partition
id: boot-partition
device: disk0
size: 2GB
- type: partition
device: disk0
id: root-partition
size: -1
- id: efi-partition-fs # format partitions on disk
type: format
volume: efi-partition
fstype: fat32
label: EFI
- id: boot-partition-fs
type: format
fstype: ext4
volume: boot-partition
- id: root-partition-fs
type: format
fstype: ext4
volume: root-partition
- id: efi-partition-fs-mount # mount partitions
type: mount
device: efi-partition-fs
path: /boot/efi
- id: root-partition-fs-mount
type: mount
path: /
device: root-partition-fs
- id: boot-partition-fs-mount
type: mount
path: /boot
device: boot-partition-fs
Added the post-processor to your JSON to export the hyper-v vhdx, but now getting the below error message, Would you please help.
hyperv-iso: WINDOWS-2016V7 restarted.
hyperv-iso: #< CLIXML
hyperv-iso: <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"><Obj S="progress" RefId="0"><TN RefId="0"><T>System.Management.Automation.PSCustomObje
ctSystem.Object1Preparing modules for first use.0-1-1Completed-1
==> hyperv-iso: Machine successfully restarted, moving on
==> hyperv-iso: Provisioning with Powershell...
==> hyperv-iso: Provisioning with powershell script: ./extra/scripts/windows-updates.ps1
==> hyperv-iso: Disconnecting from vmconnect...
==> hyperv-iso: Error shutting down VM: PowerShell error: Hyper-V\Stop-VM : Failed to stop.
==> hyperv-iso: At C:\Users\Administrator\AppData\Local\Temp\2\ps320263257.ps1:5 char:5
==> hyperv-iso: + Hyper-V\Stop-VM -VM $vm -Force -Confirm:$false
==> hyperv-iso: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> hyperv-iso: + CategoryInfo : NotSpecified: (:) [Stop-VM], VirtualizationException
==> hyperv-iso: + FullyQualifiedErrorId : OperationFailed,Microsoft.HyperV.PowerShell.Commands.StopVM
==> hyperv-iso: Clean up secondary dvd drives...
==> hyperv-iso: Clean up os dvd drive...
==> hyperv-iso: Unregistering and deleting virtual machine...
==> hyperv-iso: Deleting output directory...
==> hyperv-iso: Deleting build directory...
Build 'hyperv-iso' errored: Script exited with non-zero exit status: 2147943515. Allowed exit codes are: [0]
==> Some builds didn't complete successfully and had errors:
--> hyperv-iso: Script exited with non-zero exit status: 2147943515. Allowed exit codes are: [0]
==> Builds finished but no artifacts were created.
Hi,
For some reason after my build finishes with ubuntu 20.04.03 and I launch it in Hyper-V, I can't login. I'm using root/password and the password is always wrong. What am I doing wrong? I haven't changed anything except for the ISO.
Thanks
Hi @marcinbojko,
Following your step i did a small modification to add more FS in the LVM but the image create takes/create its LVM. I hope that can help me out to create the FS as below rather then 1 getting created of its currently
storage:
config:
- {ptable: gpt, path: /dev/sda, wipe: superblock, preserve: false, name: '', grub_device: true, type: disk, id: disk-sda}
- {device: disk-sda, size: 1M, flag: bios_grub, number: 1, preserve: false, grub_device: false, type: partition, id: partition-0}
- {device: disk-sda, size: 1G, wipe: superblock, flag: '', number: 2, preserve: false, grub_device: false, type: partition, id: partition-1}
- {device: disk-sda, size: 69G, wipe: superblock, flag: '', number: 3, preserve: false, grub_device: false, type: partition, id: partition-2}
- name: ubuntu-vg
devices: [partition-2]
preserve: false
type: lvm_volgroup
id: lvm_volgroup-0
- {fstype: xfs, volume: partition-1, preserve: false, type: format, id: format-2}
- {name: swap, volgroup: lvm_volgroup-0, size: 2G, preserve: false, type: lvm_partition, id: lvm_partition-1}
- {fstype: swap, volume: lvm_partition-1, preserve: false, type: format, id: format-3}
- {device: format-3, path: '', type: mount, id: mount-3}
- {name: var, volgroup: lvm_volgroup-0, size: 5G, preserve: false, type: lvm_partition, id: lvm_partition-2}
- {fstype: xfs, volume: lvm_partition-2, preserve: false, type: format, id: format-4}
- {name: tmp, volgroup: lvm_volgroup-0, size: 5G, preserve: false, type: lvm_partition, id: lvm_partition-3}
- {fstype: xfs, volume: lvm_partition-3, preserve: false, type: format, id: format-5}
- {name: var-log, volgroup: lvm_volgroup-0, size: 5G, preserve: false, type: lvm_partition, id: lvm_partition-4}
- {fstype: xfs, volume: lvm_partition-4, preserve: false, type: format, id: format-6}
- {name: var-log-audit, volgroup: lvm_volgroup-0, size: 5G, preserve: false, type: lvm_partition, id: lvm_partition-5}
- {fstype: xfs, volume: lvm_partition-5, preserve: false, type: format, id: format-7}
- {name: var-tmp, volgroup: lvm_volgroup-0, size: 5G, preserve: false, type: lvm_partition, id: lvm_partition-6}
- {fstype: xfs, volume: lvm_partition-6, preserve: false, type: format, id: format-8}
- {name: home, volgroup: lvm_volgroup-0, size: 10G, preserve: false, type: lvm_partition, id: lvm_partition-7}
- {fstype: xfs, volume: lvm_partition-7, preserve: false, type: format, id: format-9}
- {name: root, volgroup: lvm_volgroup-0, size: 34G, preserve: false, type: lvm_partition, id: lvm_partition-8}
- {device: format-10, path: /, type: mount, id: mount-10}
- {device: format-2, path: /boot, type: mount, id: mount-2}
- {device: format-4, path: /var, type: mount, id: mount-4}
- {device: format-5, path: /tmp, type: mount, id: mount-5}
- {device: format-6, path: /var/log, type: mount, id: mount-6}
- {device: format-7, path: /var-log-audit, type: mount, id: mount-7}
- {device: format-8, path: /var/tmp, type: mount, id: mount-8}
- {device: format-9, path: /home, type: mount, id: mount-9}
After image is created i see the lvdisplay and df -h details as below
I don't know if I miss something obvious, but when I try:
.\hv_ubuntu2204.ps1 -var 'output_directory=test'
I still get the default, "output-ubuntu2204" from
variables_ubuntu2204.pkvars.hcl
.
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.