Giter Site home page Giter Site logo

qlik-oss / mira Goto Github PK

View Code? Open in Web Editor NEW
12.0 33.0 4.0 3.63 MB

Qlik Associative Engine discovery service for orchestrated environments.

License: MIT License

Shell 4.31% JavaScript 94.11% Dockerfile 0.91% Mustache 0.67%
qix engine discovery microservice docker orchestration blackduck cla dockerbump

mira's Introduction

Mira - A Qlik Associative Engine Discovery Service

As of 1 July 2020, Qlik Core is no longer available to new customers. No further maintenance will be done in this repository.

CircleCI Renovate enabled Coverage Status

Overview

Mira provides Qlik Associative Engine discovery in a Docker containerized environment. Mira is implemented on Node.js and supports different orchestration platforms such as Docker Swarm and Kubernetes. Mira can also operate in a simpler DNS mode and a Local mode.

The documentation in this repository is primarily intended for contributors to Mira development and for those who want to improve Mira by submitting issues.

For Mira's end-user documentation, see Qlik Core documentation site.

Contributing

Contributions are welcome and encouraged! See more info at Open Source at Qlik R&D.

Docker Image

Mira is distributed to end users as a the qlikcore/mira Docker image. Also see the Dockerfile. The version file needs to be generated before building the Docker image locally.

Running Mira as a Plain Node.js Process

For convenience and development purposes, Mira can be started as a non-Dockerized Node.js process. In this case, Mira would most commonly also be used in Local mode, so the MIRA_MODE environment variable should be provided accordingly:

$ MIRA_MODE=local npm start

Development

Editor/IDE Configuration

No particular editor or IDE is assumed. The repo root contains an .editorconfig file for editors that support it. If not, make sure that the used editor is configured accordingly.

Coding Guidelines

JavaScript code shall be developed according the Airbnb JavaScript Style Guide.

The eslintrc.json file incorporates these rules with minor modifications.

Install Packages

Once the repo has been cloned, in the repo root, run:

$ npm install

Generating version file

Mira will in run-time make use of build information e.g. commit SHA and version number. This information is already present in the Mira Docker image, but if running Mira as a non-dockerized process this file (version.json) must also be available locally. The file can be generated by running the following command:

./generate_version_file.sh

Generating the OpenAPI Specification

Mira's REST API is specified in the api-doc.yml OpenAPI document. The OpenAPI specification is generated from JSDoc by running:

$ npm run generate-openapi

Circle CI

Circle CI is configured to build a new Docker image from all pushed commits on all branches of Mira. As part of this, the built Docker image is pushed to Docker Hub. If pushing to a feature branch (different from master), the Docker image is tagged with <version>-<build-number>, where <version> is fetched from package.json, and <build-number> is the automatically increased Circle CI build number given to each build. If pushing to master the image is also tagged with latest.

Testing

Unit and component tests can be run with:

$ npm run test:unit
$ npm run test:component

These tests run Mira in isolation and does not depend on any external components.

Integration tests depend on external components. Before they can run, you must accept the Qlik Core EULA by setting the ACCEPT_EULA environment variable, you start the services by using the docker-compose.yml file:

$ ACCEPT_EULA=yes docker-compose up -d
$ npm run test:integration

To run integration tests towards a specific image tag, provide the TAG environment variable to docker-compose:

$ ACCEPT_EULA=yes TAG=:<YOUR TAG HERE> docker-compose up -d
$ npm run test:integration

See package.json for more test script variants.

Releasing

Mira service release

The helper script release.sh provides a convenient way to release a new version of the service and to automatically bump versions as needed.

Check usage information in release.sh on how to perform the release and version bumping by running:

$ release.sh -?

mira's People

Contributors

abuokoene avatar axelssonhakan avatar carlioth avatar dependabot[bot] avatar dotlou avatar fredrikfolkesson avatar gabbaxx avatar greenkeeper[bot] avatar janmiderback avatar marcusoffesson avatar mikaeldanielsson avatar peol avatar qlikossbuild avatar renovate[bot] avatar sublibra avatar wennmo avatar

Stargazers

 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

mira's Issues

Implement asynchronous Engine discovery

Currently, Mira triggers Engine discovery on all REST calls to list or query for QIX Engine instances. This does not scale well with potentially having lots of requests towards Mira.

This task is to separate out the Engine discovery process from the handling of the REST API calls so that Mira instead periodically, in an asynchronous fashion, discovers Engine instances. As new engine instances are discovered or old engine instances are no longer available, the EngineList shall be updated, adding or removing EngineEntry objects from it.

Acceptance Criteria

  • Mira no longer does engine discovery on every call to the /engines endpoint.
  • Engine discovery is made periodically, possibly with an interval that is possible to configure or that Mira itself finds a suitable interval (could be based on how long a discovery scan takes).
  • Applicable tests are implemented and/or updated (unit/component/integration)

Streamline identification of engine instances between operation modes

Mira supports different operation modes of which one aspect is which orchestration environment that is used, or if none is used. The rules Mira uses to identify an engine instance in these environments differ which is natural.

However, configuring how Mira detects engine instances is not streamlined between the modes and we can probably improve. These aspects shall be addressed:

  • In local mode and swarm mode, Mira uses the Docker image name for discovery which defaults to qlikea/engine and can be set using the environment variable QIX_ENGINE_IMAGE_NAME. This env var is not used at all in the kubernetes mode.
  • In kubernetes mode, Mira relies on service port names being used and the name qix is hard-coded into Mira without any configuration possibilities.
  • Should Mira at all care about Docker image names or Kubernetes service port names for identification? Is it no possible to find a more common way, for example to use lables on containers/services/pods?

Acceptance Criteria

  • A better more streamlined way for Mira to discover engine instances shall be implemented.
  • In all modes, it shall be possible to configure (using env vars or similar) how an engine is detected and ideally, this shall be done without too much differences between the different modes.
  • Remove or rename the usage of the env var QIX_ENGINE_IMAGE_NAME as needed.
  • If relying on an environment variable for configuration, make sure that it has meaning in all different Mira modes, not just for some.

Investigate possibility to simplify and improve CCI steps for integration tests

Original Description

Check if the CCI configuration and steps can be simplified. Some things to look into:

  • There is a separate docker-compose file for integration tests that is very similar to the default compose file in the repo root. Can we use the same?
  • Can we make sure that the integration tests runs on the mira image tag build from the CCI version tag? Still only publish to Docker Hub once all is passing.
  • Also, check if documentation around running the tests can be improved and simplified.

2017-06-29 - Update after some investigations

Current problems

  • Component and integration tests do not run on CCI. We rely on local testing.
  • The test code and set up is messy. There is an integration Dockerfile that requires an external npm install to have been made.
  • We don't run component/integration tests towards the same Docker image that we publish. This introduces a small risk ("try what you fly").
  • There is no simple way to start Mira component or integration tests in the swarm and kubernetes modes. This is something that has be done locally and not on CCI so it should be as simple to just run a command, without having to configure or set up things in advance.
  • Just the number of combinations that we potentially have - running Mira non-containerized, containerized, special test build, or not - complicates a lot.

Suggestions

Unit tests

  • In dev env, run as npm run test:unit.
  • Runs on CCI with full scope also with npm run test:unit
  • Does not run containerized.
  • This is the way it works today.

Component tests

  • We limit tests to always run Mira containerized, tests trigger REST endpoints.
  • We remove the special test image build. Tests trigger endpoints externally on the "production" Mira image.
  • We accept that source level debugging requires attaching a debugger to the Mira container.
  • In a dev env, tests can still be started with npm run test:... towards the Mira container.
  • We change to build a Mira test-driver image that can be used to run tests towards the production Mira container on CCI. This image only contains test code, not Mira code.
  • We do not combine the test-driver and the production Mira images.
  • We add running the component tests with full scope on CCI.

Integration tests

  • We add so that integration tests run on CCI, similar to the component tests, but with limited scope. Only local mode will be tested on CCI.
  • We enable the test-driver image to be able to run component tests and integration tests separately, but still contained in the same test-driver image.
  • We accept that other Mira modes, such as swarm and kubernetes, has to be run on local dev machine set up. Ideally, the test-driver is able to execute the same tests, not depending on Mira mode.

Add /engines endpoint

  • Keep the /list and /query endpoints to avoid breaking other services
  • Don't forget to update documentation and tests

Keep existing formatting of queries:

  • /list == /engines with no arguments, and
  • /query == /engines?properties={}

NOTE: Looking at GraphQL will be a separate issue.

Measure code coverage of Mira's unit tests

We want code coverage of Mira's unit tests.

Acceptance Criteria

  • It shall be possible to easily run Mira unit tests and at the same time produce code coverage results as % of code covered.
  • It shall be possible, from the results, to identify exactly which lines that have not been executed.
  • Code coverage results shall always be produced on the CCI test runs.

Let Mira accept a comma-separted list in QIX_ENGINE_IMAGE_NAME

Currently, Mira only supports setting one single Engine image name in the env variable QIX_ENGINE_IMAGE_NAME.

It is not unthinkable that a deployment may have use several Engine image builds with different names.

Mira should check against against all image names provided in a comma-separated list provided in QIX_ENGINE_IMAGE_NAME.

Simplify build of Mira Docker image

With removing the rependency towards having the Qlik Artifiactory npm registry, the steps to build the Mira Docker image can probably be simplified and avoid unnecessary steps.

Suggested changes to Mira test set-up incl. CCI

Suggested changes to Mira test set up incl. CCI configuration

Current problems

  • Component and integration tests do not run on CCI. We rely on local testing.
  • The test code and set up is messy. There is an integration Dockerfile that requires an external npm install to have been made.
  • We don't run component/integration tests towards the same Docker image that we publish. This introduces a small risk ("try what you fly").
  • There is no simple way to start Mira component or integration tests in the swarm and kubernetes modes. This is something that has be done locally and not on CCI so it should be as simple to just run a command, without having to configure or set up things in advance.
  • Just the number of combinations that we potentially have - running Mira non-containerized, containerized, special test build, or not - complicates a lot.

Suggestions

Unit tests

  • In dev env, run as npm run test:unit.
  • Runs on CCI with full scope also with npm run test:unit
  • Does not run containerized.
  • This is the way it works today.

Component tests

  • We limit tests to always run Mira containerized, tests trigger REST endpoints.
  • We remove the special test image build. Tests trigger endpoints externally on the "production" Mira image.
  • We accept that source level debugging requires attaching a debugger to the Mira container.
  • In a dev env, tests can still be started with npm run test:... towards the Mira container.
  • We change to build a Mira test-driver image that can be used to run tests towards the production Mira container on CCI. This image only contains test code, not Mira code.
  • We do not combine the test-driver and the production Mira images.
  • We add running the component tests with full scope on CCI.

Integration tests

  • We add so that integration tests run on CCI, similar to the component tests, but with limited scope. Only local mode will be tested on CCI.
  • We enable the test-driver image to be able to run component tests and integration tests separately, but still contained in the same test-driver image.
  • We accept that other Mira modes, such as swarm and kubernetes, has to be run on local dev machine set up. Ideally, the test-driver is able to execute the same tests, not depending on Mira mode.

Make Mira API Governance compliant

Mira is currently not monitored by API Governance, but before public release we need to be compliant with API Governance rules.

This task includes enabling the monitoring, but also validate and verify that the swagger spec, versioning etc is compliant.

Enable Mira local mode integration tests in CCI

In issue #85, a Mira integration test script shall be developed. Since we shall run Mira integration tests on local mode on CCI, the CCI configuration should take benefit of, and use this script.

Acceptance Criteria

  • All commits to the Mira repo trigger the local mode integration tests by invoking the test script.
  • Integration test failures prevent PRs from being merged to master.
  • It must be possible to identify what integration test cases that fail.

Add kubernetes mode

  • Create a pod definition that gives the mira container access to the kubernetes api server
  • Add a kubernetes mode to mira that uses the endpoints api to get the list of hosts/ports

Investigate and prototype using GraphQL for Mira engine queries

Currently, engine properties can be queried in a non-standardized format.
This issue is about investigating and prototyping using GraphQL for querying engines with certain properties.

The expected outcome of this task is a "go" or "no go" to whether we should introduce GraphQL on the Mira /engines endpoint. If we should use GraphQL a new issue shall be created for the actual implementation with all related work (documentation updates, testing etc.)

Related to this task is also the need for a better API specification for Mira. Currently, engine information returned from Mira is not strictly defined, which makes it hard for a consumer of the Mira API to formulate queries. This affects how GraphQL can be used, but is also a separate task from this.

Create Kubernetes cluster for Mira integration tests

When running Mira integration tests, some of them require Mira to run in a Kubernetes cluster together with QIX Engine services.

It is uncertain of such a Kubernetes cluster can be hosted and created dynamically on CCI so we probably need to host such a cluster (static or dynamic) at some other location so that test cases relying on Kubernetes can be triggered on commits to the Mira repo.

This task is about figuring out how to host such a cluster and create it (not about setting up the CI pipeline to run the tests).

Mira lists qix engines that are not yet ready for sessions

When deploying the custom-analytics use case to a swarm and scaling up by adding worker nodes, mira seems to list qix engines that are not yet ready for connections.

  1. Create a swarm cluster
  2. Deploy stack
  3. Run e2e tests for e.g. custom-analytics a couple of times to see that the traffic is evenly distributed between nodes e.g. using kibana.
  4. Scale up workers with 1
  5. Run e2e tests again

Result:
Just after scaling up a worker there is a period of time when sessions are forwarded to the new qix engine, which fails to open sessions and the e2e tests will fail. The "old" worker nodes are fine.

Investigate if we need to have two docker-compose files, preferably only have one

Currently, Mira has two different docker-compose files.. One for creating mira and engine containers locally and one for running integration tests. They are almost identical but the second one builds mira instead of running a specified image label. This is probably unnecessary and we should be able to use only one such compose file by simplfying build steps and the CCI configuration.

Acceptance Criteria

  • Only one docker-compose file exists and works both for local set up on dev machine and for CCI purposes.
  • CCI configuration is updated as needed.
  • If not possible to use singe file, document the reasons here in this issue and close.

Enable Greenkeeper for Mira

Enable Greenkeeper for mira - https://greenkeeper.io/

  • Greenkeeper does not seem to be avaible for qlik-ea organization, new account/set-up needed?
  • Add Greenkeeper badge to README.md
  • Don't update automatically, the set-up should create a branch with PR for each NPM package update

Create script for running integration tests locally for all Mira modes

Since we will not implement running integration tests for the swarm and kubernetes modes on CCI, we need a script that can set up Docker Swarm and Kubernetes environments locally on dev machine and that runs the Mira integration tests in these modes locally. Running these integration tests will be a manual step, and the script shall be designed so that this is easily done from the command line. Later we shall investigate other options for running these tests as part of CI, but for v1 we will rely on manual testing on developers machines.

Acceptance Criteria

  • There is a shell script that runs Mira integration tests on local, swarm, and kubernetes modes.
  • It shall be possible to specify, as options to the script:
    -- which mode to test (possibly with an "all" option, to run tests for all modes).
    -- if the Mira Docker image shall be built before running the tests.

Handling of versioning in Mira

This tasks includes investigating how versioning is handled today in Mira, and what is needed to be improved before a public release.

Some questions:

  • Should component version differ from API version?
  • Should version be set manually or automatically generated?
  • Are we compliant with API Governance with regards to semantic versioning?

Enable Mira component tests in CCI

Enable Mira component tests to run in CCI job. The tests shall

  • Be run on CCI all commits
  • Run by doing an npm install followed by npm run test:component
  • There shall be no need for any other external services. Hence no need for any docker-compose files
  • These tests shall not run "dockerized". No Mira Docker image shall be needed to run the tests on

Standardized Query Language

We should use a standardized query language instead of using something we build ourselves.

This could be GraphQL or something else.

Acceptance Criteria

  • Decided on a query language to use
  • Implemented the query language

Make mira internally asynchronous

Currently all information is fetched synchronously per request. Information gathering should be asynchronously.

Design Proposal

The current call chain is divided into three parts

The engine discovery process

Discovering engines using kubernetes/docker swarm is handled by it's own setTimeout-loop. The resulting array of engines is fed into a map called currentStateMap like so:

  • If an engine entry discovered is missing in the currentStateMap a new health checker setTimeout-loop is created for that engine.
  • All entries in the currentStateMap that don't have a a corresponding item in the recently discovered list of engines are pruned from the currentStateMap and their corresponding health checker setTimeout-loop is marked for termination.

The health checker process

The health checker process is a setTimeout-loop that calls the engine health API and generates the properties set for that engine.

  • The health information is entered into the engine entry in the currentStateMap.
  • If an entry for the engine at hand is missing it has been removed by the discovery mechanism and the health checker will be canceled.
  • Health failure should not remove the engine from the currentStateMap, rather mark it as down. Removal is handled by the discovery process.

Note that each engine must have it's own setTimeout-loop since various network problems can cause large timeouts.

The API call

The API call (/v1/engines) now simply fetches information from the currentStateMap and filters out engines marked as down.

Write Mira component tests

Mira has no component tests. Since the coverage of integration tests for Mira's different operation modes are limited, a larger effort should be put into writing component tests. Running the component tests shall not require access to a true Docker Engine APIs or a true Kubernetes master, such dependencies shall be mocked so that it is possible to run these tests in CCI without the need to set up such clusters.

This is a pretty large issue and may need to be split up into several smaller ones. A first step is probably to try to identify which test cases we want and how the mocking of dependencies shall be done.

Enabling the component tests on CCI is covered in #32.

Check hard-coded values and move to config

Today there exists some magic hard coded values. These should be lifted out to the config file so we can configure them.

Acceptance Criteria
All values that reasonable might want to be changed should be moved out to the config file and populated from it.

Mira does not work properly when engine exposes more than one port

In qlikea/engine 12.45.0, there are two ports exposed. One for QIX interface and one for the /metrics endpoint. Mira probably assumes that engine only exposes one port for the QIX interface and may return the incorrect port as QIX interface (port property in the response).

We must consider if it is worth for Mira to try to make smart decisions on this based on the response from the Docker or Kubernetes APIs, if this should just be a configuration value to Mira, or if we should not return any port info at all and assume that the what ever service that want to connect to an engine, knows by other means which port to use.

Make mira internally asynchronous (Epic)

Currently all information is fetched synchronously per request. Information gathering should be asynchronously.

Design Proposal

The current call chain is divided into three parts

The engine discovery process

Discovering engines using kubernetes/docker swarm is handled by it's own setTimeout-loop. The resulting array of engines is fed into a map called currentStateMap like so:

  • If an engine entry discovered is missing in the currentStateMap a new health checker setTimeout-loop is created for that engine.
  • All entries in the currentStateMap that don't have a a corresponding item in the recently discovered list of engines are pruned from the currentStateMap and their corresponding health checker setTimeout-loop is marked for termination.

The health checker process

The health checker process is a setTimeout-loop that calls the engine health API and generates the properties set for that engine.

  • The health information is entered into the engine entry in the currentStateMap.
  • If an entry for the engine at hand is missing it has been removed by the discovery mechanism and the health checker will be canceled.
  • Health failure should not remove the engine from the currentStateMap, rather mark it as down. Removal is handled by the discovery process.

Note that each engine must have it's own setTimeout-loop since various network problems can cause large timeouts.

The API call

The API call (/v1/engines) now simply fetches information from the currentStateMap and filters out engines marked as down.

Add ReDoc API documentation to Mira linked from README.md

README.md contains an API section which should point to a page giving a ReDoc formatted API doc.

The ReDoc HTML file containing the redoc tag and pointing to the OpenAPI yml file must be served as a proper web page. The HTML will not be displayable from GitHub unless it is served through GitHub Pages which will be public even though repos are not exposed.

As discussed with Andrée it is possible that we want to do a small Elastic "documentation" deployment to AWS (or alternative) to expose the Elastic documentation including API specs and use the "Qliktive" Authentication service to grant access to the correct audience.

Implement EngineList

The data model of Mira shall have an EngineList implementation holding a list of EngineEntry objects.
This list shall work as a central in-memory repository of discovered QIX Engine instances. The entries of the list will be modified by Mira's' engine discovery process (not part of this task). The list shall contain EngineEntry objects (implementation of the EngineEntry class is not part of this task.

Acceptance Criteria

  • Class EngineList implemented in its own file.
  • The implementation shall provide necessary operations to modify the list.
  • It shall be possible to filter the list based on certain properties of the EngineEntry objects in the list.
  • Applicable unit tests written.
  • It is ok for the list to be populated with dummy EngineEntry objects if the implementation of EngineEntry is not available.

Add support for Mira in Kubernetes mode

This issue may need to be broken down into several smaller tasks.

Currenlty mira supports QIX Engine discovery in a Docker Swarm environment.
We need Mira to support Kubernetes as well.

How Kubernetes affects Mira with respect to this is not yet known and needs to be investigated first.

Implement EngineEntry

The data model of Mira shall have an EngineEntry implementation. This class shall represent one QIX Engine instance as discovered by Mira's discovery process.

It shall contain an internal periodically triggered health check towards the Engine instance and update its state accordingly. The class shall be able to hold all QIX Engine state and properties that is relevant for Mira.

Acceptance Criteria

  • EngineEntry implemented in separate file as class fulfilling the requirements above.
  • On failed Engine health checks (health bad or Engine does not respond) EngineEntry may need to support event notifications on this.
  • Unit tests as applicable are implemented.

Mira not working in Swarm mode

When running mira in Swarm mode it is timing out when trying to get the status from the engines. It is working fine in local mode.

Errors from mira container console...

{"level":"info","message":"Swarm Mode Docker Client requested","timestamp":"2017-06-16T20:11:08.943Z"}
{"level":"info","message":"Listening on port 9100","timestamp":"2017-06-16T20:11:08.973Z"}
{"level":"error","message":"Engine health check got HTTP error response: Error: connect ETIMEDOUT 10.255.0.7:9076","timestamp":"2017-06-16T20:14:05.458Z"}
{"level":"warn","message":"Healthcheck failed for engine { properties: { 'com.docker.stack.namespace': 'mira-stack', healthy: false },\n  ipAddress: '10.255.0.7',\n  port: 9076,\n  publicPort: 9276,\n  networks: \n   [ { name: 'ingress', addresses: [Object] },\n     { name: 'mira-stack_default', addresses: [Object] } ] } No connection to engine","timestamp":"2017-06-16T20:14:05.462Z"}

repeats for each of the 3 engines running.

Update Mira API - both implementation and documentation

The Mira API shall be updated. The response on the /engines endpoint should be an array of JSON object as follows:

{
    "ipAddress":           "<engine API address>",
    "hostName":            "<host name of engine", // only present if possible to obtain
    "port":                <engine QIX interface port (websocket)>,
    "metricsPort":         <engine metrics endpoint port>,
    "lastHealthResponse":  "<time and date of last health response from engine>",
    "lastMetricsResponse": "<time and date of last metrics response from engine>",
    "health":              { <engine health response (unmodified)> },
    "metrics":             { <engine metrics response (unmodified)> },
    "labels":              { <all engine labels extracted from the orchestration platform> }
    "local":               { <Docker Engine API response for engine container (unmodified)> },  // only present in Mira "local" mode
    "swarm":               { <Docker Engine API response for engine task (unmodified)> }, // only present in Mira "swarm" mode
    "kubernetes":          { <Kubernetes API response for engine pod (unmodified)> } // only present in Mira "kubernetes" mode.
}
  • Update the implementation to comply with this API
  • Update tests
  • Update documentation incl. OpenAPI spec.
  • Remove all logic related to querying, which we decided not to include in v1 scope

Create Docker Swarm cluster for Mira integration tests

When running Mira integration tests, some of them require Mira to run in a Docker Swarm cluster together with QIX Engine services.

It is uncertain of such a Swarm cluster can be hosted and created dynamically on CCI so we probably need to host such a cluster (static or dynamic) at some other location so that test cases relying on Swarm can be triggered on commits to the Mira repo.

This task is about figuring out how to host such a cluster and create it (not about setting up the CI pipeline to run the tests).

Add metric endpoint for Mira

All microservices should provide an metric endpoint for monitoring of e.g. load and health monitoring. Mira does not provide that at the moment.

For example Mira could provide metrics on number of requests for engines.

This endpoint should of course also be part of the swagger spec and documentation

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.