Coder Social home page Coder Social logo

pullio's Introduction

Documentation

All our documentation is located at hotio.dev.

Support

If you need some assistance, please join our discord server.

Source

The source is hosted at GitHub. If you can't find it in the master branch, it's probably located in another branch.

Show your support

You can show your support by giving us a star on Docker Hub or/and GitHub, it's also possible to make a donation.

pullio's People

Contributors

mrhotio avatar nuxencs avatar quorn23 avatar saltydk avatar sammcj avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pullio's Issues

Failure when pulling due to docker compose naming

If I do not explicitly set container_name to the same name as the service in the YAML config, pulls will fail. Take this docker-compose.yml as an example:

version: "3.7"

services:
  db:
    image: mysql:8.0.15

  redis:
    image: redis

  app:
    image: nextcloud:20-apache
    labels:
      - "org.hotio.pullio.notify=true"
      - "org.hotio.pullio.update=true"
      - "org.hotio.pullio.discord.webhook=https://discord.com/api/webhooks/SNIP"

  cron:
    image: ...

I also modified line 145 in pullio.sh to not silence the errors after running the pull. Running pullio gives me this:

nextcloud_app_1: Checking...
nextcloud_app_1: Pulling image...
ERROR: No such service: nextcloud_app_1
nextcloud_app_1: Pulling failed!
nextcloud_cron_1: Checking...
nextcloud_db_1: Checking...
nextcloud_redis_1: Checking...

The correct command should be docker-compose pull app, but it is instead doing docker-compose pull nextcloud_app_1, which isn't working. I am not familiar with the implementation, but it seems like you are doing docker ps instead of docker-compose ps to get the container names. You need the service names, not the container names.

Running Pullio getting error "Error response from daemon: Get "https://cr.hotio.dev/v2/": dial tcp: lookup cr.hotio.dev on 192.168.0.1:53: no such host"

Log

Running with "DEBUG=" and "TAG=". Current version: 0.0.6 Latest version: 0.0.6 FlareSolverr: Checking... cloudflare-tunnels: Checking... dashy: Checking... ddns-updater: Checking... docker-socket-proxy: Checking... dozzle: Checking... dozzle: Pulling image... time="2024-02-11T00:00:06-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:06-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:06-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." dozzle Pulling dozzle Pulled homepage: Checking... plex: Checking... plex: Pulling image... time="2024-02-11T00:00:08-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:08-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:08-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." plex Pulling plex Error Error response from daemon: Get "https://cr.hotio.dev/v2/": dial tcp: lookup cr.hotio.dev on 192.168.0.1:53: no such host plex: Pulling failed! portainer: Checking... prowlarr: Checking... prowlarr: Pulling image... time="2024-02-11T00:00:10-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:10-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:10-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." prowlarr Pulling prowlarr Error Error response from daemon: Get "https://cr.hotio.dev/v2/": dial tcp: lookup cr.hotio.dev on 192.168.0.1:53: no such host prowlarr: Pulling failed! qbitmanage: Checking... qbitmanage: Pulling image... time="2024-02-11T00:00:11-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:11-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:11-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." qbit_manage Pulling qbit_manage Pulled qbittorrent: Checking... qbittorrent: Pulling image... time="2024-02-11T00:00:12-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:12-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:12-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." qbittorrent Pulling qbittorrent Error Error response from daemon: Get "https://cr.hotio.dev/v2/": dial tcp: lookup cr.hotio.dev on 192.168.0.1:53: no such host qbittorrent: Pulling failed! radarr: Checking... radarr: Pulling image... time="2024-02-11T00:00:13-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:13-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:13-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." radarr Pulling radarr Error Error response from daemon: Get "https://cr.hotio.dev/v2/": dial tcp: lookup cr.hotio.dev on 192.168.0.1:53: no such host radarr: Pulling failed! readarr: Checking... readarr: Pulling image... time="2024-02-11T00:00:14-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:14-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:14-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." readarr Pulling readarr Pulled recyclarr: Checking... sonarr: Checking... sonarr: Pulling image... time="2024-02-11T00:00:16-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:16-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:16-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." sonarr Pulling sonarr Error Error response from daemon: Get "https://cr.hotio.dev/v2/": dial tcp: lookup cr.hotio.dev on 192.168.0.1:53: no such host sonarr: Pulling failed! tautulli: Checking... tautulli: Pulling image... time="2024-02-11T00:00:17-05:00" level=warning msg="The \"PLEX_CLAIM\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:17-05:00" level=warning msg="The \"PLEX_ADVERTISE_IP\" variable is not set. Defaulting to a blank string." time="2024-02-11T00:00:17-05:00" level=warning msg="The \"PLEX_PASS\" variable is not set. Defaulting to a blank string." tautulli Pulling tautulli Error Error response from daemon: Get "https://cr.hotio.dev/v2/": dial tcp: lookup cr.hotio.dev on 192.168.0.1:53: no such host tautulli: Pulling failed! vaultwarden: Checking... youtubedl-material: Checking... Pruning docker images... Total reclaimed space: 0B

Can't find docker compose

After adding pullio labels to docker-compose files in Portainer, and manually running:

sudo /usr/local/bin/pullio

I get the following error for each stack that:

Running with "DEBUG=" and "TAG=".
bazarr: Checking...
duckdns: Checking...
duckdns: Pulling image...
/usr/local/bin/pullio: line 33: cd: /data/compose/29: No such file or directory

After looking through the pullio script, it would appear that the issue is caused when getting the compose working directory. After running:

 DOCKER_BINARY="$(which docker)"
container_name="bazarr"
sudo "${DOCKER_BINARY}" inspect --format='{{ index .Config.Labels "com.docker.compose.project.working_dir" }}' "$container_name"

I get:

/data/compose/45

Re-running it just as:

"${DOCKER_BINARY}" inspect "$container_name"

I get a JSON dump. Of particular interest:

                "com.docker.compose.project.config_files": "/data/compose/45/docker-compose.yml",
                "com.docker.compose.project.working_dir": "/data/compose/45",

Complete dump below.

What's going on here?

[
    {
        "Id": "b73565e50bc85a1d64eda349a069000522817812e09e9757502ce0cfc960872f",
        "Created": "2021-09-30T06:10:36.780961096Z",
        "Path": "/init",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 19512,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-09-30T06:10:37.796972963Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:4d1df9f7968c6edc6acfff613fdd2887c1ad27310231afcccfd92f6551e2a643",
        "ResolvConfPath": "/var/lib/docker/containers/b73565e50bc85a1d64eda349a069000522817812e09e9757502ce0cfc960872f/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/b73565e50bc85a1d64eda349a069000522817812e09e9757502ce0cfc960872f/hostname",
        "HostsPath": "/var/lib/docker/containers/b73565e50bc85a1d64eda349a069000522817812e09e9757502ce0cfc960872f/hosts",
        "LogPath": "/var/lib/docker/containers/b73565e50bc85a1d64eda349a069000522817812e09e9757502ce0cfc960872f/b73565e50bc85a1d64eda349a069000522817812e09e9757502ce0cfc960872f-json.log",
        "Name": "/bazarr",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "docker-default",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": [
                "/srv/dev-disk-by-uuid-60031315-529e-40c3-b97c-23917ebfb57c/Bazarr:/config:rw"
            ],
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "bazaar_default",
            "PortBindings": {
                "6767/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "6767"
                    }
                ]
            },
            "RestartPolicy": {
                "Name": "",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": [],
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": null,
            "DnsOptions": null,
            "DnsSearch": null,
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": null,
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": null,
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/04d9b8633335d1d8b75916abaf199686cf7b70935fb85fa7de4af36459cc5ecd-init/diff:/var/lib/docker/overlay2/14f06b37ace1fb3f756a984f0322ab217f25fc33146cd27fd3ff1361589f7008/diff:/var/lib/docker/overlay2/b17116d4de239e7aae0d272806c7e2c874df8f0f809b79f26e166ce63acf6232/diff:/var/lib/docker/overlay2/5439793015faab71f2e65f0c82aa339d6faecf719eff4fd192226cb9e60ccad2/diff:/var/lib/docker/overlay2/4aa1c08ac0256c6371db54f615d62e3a6b42038dda1bb40fed7175fd1fe6bad5/diff:/var/lib/docker/overlay2/9670c0bf4ea3a811aeaa21d96abf2e21d8b2e450a14ae4e59e4a2c9cd6568378/diff:/var/lib/docker/overlay2/cc1f260f2ca83522546390576d55451851c3e98ee96876a10f3a1562c9ee0faa/diff:/var/lib/docker/overlay2/e10eae683f32bdbc54adf4382443f159b8c33ae9d32c22b5bf1157b77cce8bd4/diff:/var/lib/docker/overlay2/0f26d3853ef3994ec3ae020932b25bd1848f5820c478da58fe87ed23a2296b77/diff",
                "MergedDir": "/var/lib/docker/overlay2/04d9b8633335d1d8b75916abaf199686cf7b70935fb85fa7de4af36459cc5ecd/merged",
                "UpperDir": "/var/lib/docker/overlay2/04d9b8633335d1d8b75916abaf199686cf7b70935fb85fa7de4af36459cc5ecd/diff",
                "WorkDir": "/var/lib/docker/overlay2/04d9b8633335d1d8b75916abaf199686cf7b70935fb85fa7de4af36459cc5ecd/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/srv/dev-disk-by-uuid-60031315-529e-40c3-b97c-23917ebfb57c/Bazarr",
                "Destination": "/config",
                "Mode": "rw",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
        "Config": {
            "Hostname": "b73565e50bc8",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": true,
            "AttachStderr": true,
            "ExposedPorts": {
                "6767/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PGID=100",
                "TZ=Australia/Sydney",
                "UMASK=002",
                "PUID=997",
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "APP_DIR=/app",
                "CONFIG_DIR=/config",
                "ARGS=",
                "XDG_CONFIG_HOME=/config/.config",
                "XDG_CACHE_HOME=/config/.cache",
                "XDG_DATA_HOME=/config/.local/share",
                "LANG=C.UTF-8",
                "LC_ALL=C.UTF-8",
                "S6_BEHAVIOUR_IF_STAGE2_FAILS=2",
                "BUILD_ARCHITECTURE=linux-arm64"
            ],
            "Cmd": null,
            "Image": "sha256:4d1df9f7968c6edc6acfff613fdd2887c1ad27310231afcccfd92f6551e2a643",
            "Volumes": {
                "/config": {}
            },
            "WorkingDir": "",
            "Entrypoint": [
                "/init"
            ],
            "OnBuild": null,
            "Labels": {
                "com.docker.compose.config-hash": "05ce9711a28d06cf96161b281904876a2ede2ea04451f6e13ae2c45b04ee89b1",
                "com.docker.compose.container-number": "1",
                "com.docker.compose.oneoff": "False",
                "com.docker.compose.project": "bazaar",
                "com.docker.compose.project.config_files": "/data/compose/45/docker-compose.yml",
                "com.docker.compose.project.working_dir": "/data/compose/45",
                "com.docker.compose.service": "bazarr",
                "com.docker.compose.version": "2.0.0",
                "org.hotio.pullio.update": "true",
                "org.opencontainers.image.created": "2021-09-11T13:15:37Z",
                "org.opencontainers.image.revision": "912a6904b012e19a8f8d2936f75643daa537108e",
                "org.opencontainers.image.source": "https://github.com/hotio/bazarr/tree/release",
                "org.opencontainers.image.title": "hotio/bazarr:release",
                "org.opencontainers.image.url": "https://github.com/hotio/bazarr/blob/master/README.md",
                "org.opencontainers.image.vendor": "hotio",
                "org.opencontainers.image.version": "0.9.9"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "83a9fc88d83a254221da16a10433cded610e541d2da0d6f7c975444a419ae8cd",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "6767/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "6767"
                    },
                    {
                        "HostIp": "::",
                        "HostPort": "6767"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/83a9fc88d83a",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "",
            "Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "MacAddress": "",
            "Networks": {
                "bazaar_default": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": [
                        "bazarr",
                        "bazarr",
                        "b73565e50bc8"
                    ],
                    "NetworkID": "6af4f1689e529b98027423e17b46ae4fae897f1994dbc4aa3a15bfd24118407f",
                    "EndpointID": "6d5b30eb46d8786c68917456fec1f8f5f8904af473fa0c5c54622880167c3679",
                    "Gateway": "172.19.0.1",
                    "IPAddress": "172.19.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:13:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

Support multiple instances of radarr

Hello! Thank you for this script! I used it for the first time yesterday and it worked great except it seemed to choke on my second instance of radarr.

I'm running two radarr containers: one named radarr and one named radarr-standup. I wish I had saved the output for this bug report, but the script didn't seem to like that it was named radarr-standup. The result was that my radarr-standup container was removed and my radarr container was left stopped.

Is there a way to run the script or configure my setup such that two radarrs can be supported? Thanks much for the help!

Can you add a link to the repo?

I read the images in the readme, but only after a second pass did I realise there was a link there. I automatically search the repo about section in GitHub for links to the web site of a project. Could you add the web site there? I can't submit a PR as it's only editable by repo admins.

Script never updates anything

Just prunes images and that’s it. I have it in root crontab like so

0 4 * * *�������/usr/local/bin/pullio

And this is what I get when it runs

Running with "DEBUG=" and "TAG=".
jackett: Checking...
nzbhydra2: Checking...
ombi: Checking...
overseerr: Checking...
radarr: Checking...
resilio-sync: Checking...
sonarr: Checking...
tautulli: Checking...
traefik: Checking...
znc: Checking...
Pruning docker images...
Total reclaimed space: 0B

Running it in debug mode does nothing different. What am I doing wrong here? I’ve added all the tags to my docker-compose.yml and example

nzbhydra2:
image: linuxserver/nzbhydra2:latest
container_name: nzbhydra2
restart: unless-stopped
expose:
- "5076"
labels:
- "traefik.http.routers.nzbhydra.rule=Host(testing.test.org)"
- "traefik.http.routers.nzbhydra.entrypoints=websecure"
- "traefik.http.routers.nzbhydra.tls.certresolver=route53"
- "traefik.http.routers.nzbhydra.middlewares=authtraefik"
- "traefik.http.routers.nzbhydra.middlewares=sslheader"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
- "org.hotio.pullio.notify=true"
- "org.hotio.pullio.update=true"
- "org.hotio.pullio.generic.webhook=https://maker.ifttt.com/trigger/Pullio/with/key/fake-api-key"
- "org.hotio.pullio.author.avatar=https://s.gravatar.com/avatar/99420eb3d52581434d66b08cf67f2e85"
environment:
- PUID=65534
- PGID=65534
- TZ=America/Los_Angeles
volumes:
- "/opt/docker-data/nzbhydra:/config"
- "/mnt/freenas/downloads:/downloads"

so what am I doing wrong?

Compose V2 support?

With the new docker compose could we get a detection for it, so it won't spin up linuxserver/docker-compose on machines without docker-compose?

Possible to only notify of update, without downloading the image?

with pull the images are downloaded. Is it possible to configure the script, when notifying only, to check for updates without pulling the images in? I haven't found a command actually in the docker compose doc that does that (check current version against available one without downloading the image).

other notifications methods

hi

do you have plans to support other notifications methods? the specific one i am thinking of is pushover because i already us it for all my Arr server notifications. i would be happy to take a crack at implementing this if you don't have time.

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.