1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

chore: Fix formatting all the things

This commit is contained in:
ivaosthu 2018-11-22 11:20:28 +01:00 committed by Ivar Conradi Østhus
parent b24a7b06f3
commit 8a53d8dca2
31 changed files with 808 additions and 782 deletions

View File

@ -1,31 +1,31 @@
sudo: false
language: node_js
node_js:
- '8'
- '10'
- '8'
- '10'
env:
matrix:
- DATABASE_URL=postgres://postgres@localhost:5432/unleash_test TEST_DATABASE_URL=postgres://postgres@localhost:5432/unleash_test
global:
secure: HyWYh1dbUfe2yPF9ZdcdA/IVGyNWmJmpuaRvRGnnpO63/5Y0KT6/hyL6nZ4YJ7Wr/KEt4eMJBJsnzaCFtiqNA3cWyyprzXJButw0o8C6dfd/9jOleisuvdqndu92RqDKIIq2EjHVq3sd6B8uGyiOlkMsyFH57O/V+xHW8MYLnaQ=
matrix:
- DATABASE_URL=postgres://postgres@localhost:5432/unleash_test TEST_DATABASE_URL=postgres://postgres@localhost:5432/unleash_test
global:
secure: HyWYh1dbUfe2yPF9ZdcdA/IVGyNWmJmpuaRvRGnnpO63/5Y0KT6/hyL6nZ4YJ7Wr/KEt4eMJBJsnzaCFtiqNA3cWyyprzXJButw0o8C6dfd/9jOleisuvdqndu92RqDKIIq2EjHVq3sd6B8uGyiOlkMsyFH57O/V+xHW8MYLnaQ=
before_install: npm install -g greenkeeper-lockfile@1
before_script:
- psql -c 'create database unleash_test;' -U postgres
- greenkeeper-lockfile-update
- psql -c 'create database unleash_test;' -U postgres
- greenkeeper-lockfile-update
script: yarn run test:coverage
after_script: greenkeeper-lockfile-upload
after_success:
- yarn run test:coverage-report
after_success:
- yarn run test:coverage-report
notifications:
slack:
secure: MroremSKwtQkwPbrXjgs9hIqKTCDKk7bAIXXzjcS6wXC9uRaFgwFaW8oO3vBxtWa4BL44EQBLE/rboWgqFER62+XgXNgEqGZqrcJHJvby4r+dUNMPI64OZvWdIiydIYxLo8C1C4x5PqBup0xuLq8h/SBnNvA2NLgkjuvzOi+v/Q=
slack:
secure: MroremSKwtQkwPbrXjgs9hIqKTCDKk7bAIXXzjcS6wXC9uRaFgwFaW8oO3vBxtWa4BL44EQBLE/rboWgqFER62+XgXNgEqGZqrcJHJvby4r+dUNMPI64OZvWdIiydIYxLo8C1C4x5PqBup0xuLq8h/SBnNvA2NLgkjuvzOi+v/Q=
addons:
postgresql: '9.4'
postgresql: '9.4'
cache:
yarn: true
yarn: true
deploy:
# deploy doc on master to production
- provider: script
script: bash scripts/deploy-docs.sh
on:
branch: master
# deploy doc on master to production
- provider: script
script: bash scripts/deploy-docs.sh
on:
branch: master

View File

@ -1,29 +1,35 @@
# Changelog
## 3.1.2
- fix(clientApi): Add namePrefix paramter to /api/client/features
## 3.1.1
- fix(gzip): Add gzip support
- fix(package): update unleash-frontend to version 3.1.3
## 3.1.0
- fix(package): update unleash-frontend to version 3.1.1
## 3.0.6
- fix(log4js): Upgrade log4js to version 3.0.3 and fix default log configuration
## 3.0.5
- fix(package): update log4js to version 3.0.2
- fix(package): update knex to version 0.15.2
- fix(package): update yargs to version 12.0.1
- chore(readme): Update documentation
- fix(package): update install to version 0.12.0
- fix(revive): Include user information on revive
- fix(revive): Include user information on revive
- chore(package): update eslint to version 5.0.0
- chore(package): update nyc to version 12.0.1
## 3.0.4
- feat(metrics): Expose toggle updates to prometheus
- chore(package.json): Bump serve-favicon to 2.5.0
- chore(package.json): Bump joi to 13.0.3
@ -36,31 +42,37 @@
- chore(package.json): Bump commander to 2.15.1
## 3.0.3
- feat(bind): Added option to bind to specific http address
- fix(migration): Unleash should not start if migration fails.
## 3.0.2
- fix(package): Update unleash-frontend to version 3.0.1
- fix(package): Update unleash-frontend to version 3.0.1
## 3.0.1
- fix(package): Update db-migrate-pg to version 0.4.0
- fix(package): update prom-client to version 11.0.0
- refactor: use body-parser bundled with express
- fix(package): update express-validator to version 5.0.0
## 3.0.0 (10.02.2018)
- All changes in all 3.0.0 alpha-releases is included in this version
- fix(package): Upgrade unleash-frontend to version 3.0.0
## 3.0.0-alpha.10
- chore(package.json): Bump unleash-frontend to 3.0.0-alpha.7
- fix(store): DB should not override createdAt if set.
## 3.0.0-alpha.9
- Bugfix: more informative name validation errors ([#292](https://github.com/Unleash/unleash/pull/292))
## 3.0.0-alpha.8
- [Auth] User-provider ([#261](https://github.com/Unleash/unleash/issues/261))
- [Auth] Document how to secure Unleash ([#234](https://github.com/Unleash/unleash/issues/234))
- [Auth] Admin UI should handle 401 ([#232](https://github.com/Unleash/unleash/issues/232))
@ -69,16 +81,20 @@
- [Auth] Support sign out ([#288](https://github.com/Unleash/unleash/issues/288))
## 3.0.0-alpha.7
- Bugfix: Should not allow creation of archived toggle #284
## 3.0.0-alpha.6
- Expose vresion number in /api and in user interface.
- Expose vresion number in /api and in user interface.
- Housekeeping: Upgrading a lot of dependencies
## 3.0.0-alpha.3
- Bump unleash-frontend
## 3.0.0-alpha.2
- Add sdkVersion in client registration
- disable edit of built-in strategies
- Strip uknown fields in client requests.
@ -86,66 +102,73 @@
- Add posibility to inject custom logger provider
## 3.0.0-alpha.1
- upgrade unleash-frontend to 3.0.0-alpha.1
- moved api endpoints to /api/admin/* and /api/client/*
- moved api endpoints to /api/admin/_ and /api/client/_
- refactored all routes to use a standalone router per file
- removed v.1 legacy data support
- removed v.1 legacy /features endpoint
- added prettier and upgraded eslint
## 2.2.0
- Expose hooks in main export #223
## 2.1.7
- Bump unleash-frontend to 2.2.6
## 2.1.6
- Added strategies validation when updating feature toggle
- Allow node newer than 6 to run the app
## 2.1.4
- Bump unleash-fronted to 2.2.4
## 2.1.3
- Bugfix for db: timestamps should be with time zone.
- Bump unleash-fronted to 2.2.3
## 2.1.2
- Bugfix for migration: avoid multiple calls on same callback.
## 2.1.0
- Provide a set of pre-defined activation strategies. These will automatically be defined by the migrator as long as they don't exist already.
- applicationHostname
- gradualRolloutRandom
- gradualRolloutSessionId
- gradualRolloutUserId
- remoteAddress
- userWithId
- Provide a set of pre-defined activation strategies. These will automatically be defined by the migrator as long as they don't exist already.
- applicationHostname
- gradualRolloutRandom
- gradualRolloutSessionId
- gradualRolloutUserId
- remoteAddress
- userWithId
## 2.0.4
- bump unleash-frontend which includes a lot of UI improvements and bug-fixes.
- Fix error message when trying to create a archived feature toggle.
- Fix error message when trying to create a archived feature toggle.
## 2.0.0 (January 2017)
- Support multiple strategies. This makes it easy to use multiple activation strategies in combination.
- Client metrics. Gives details about what toggles a specific client application uses, how many times a toggle was evaluated to true / false. Everything presented in the UI.
- Client registration. This gives insight about connected clients, instances, strategies they support.
- Client metrics. Gives details about what toggles a specific client application uses, how many times a toggle was evaluated to true / false. Everything presented in the UI.
- Client registration. This gives insight about connected clients, instances, strategies they support.
- Client Application overview. Based on metrics and client registrations.
- Database-migration done internally by Unleash, no external migration step required.
- Publish unleash-server to npm.
- Database-migration done internally by Unleash, no external migration step required.
- Publish unleash-server to npm.
- Provide Prometheus endpoint for service metrics (response times, memory usage, etc).
- A lot of bug-fixes (check commit history and issues for reference)
- Unleash-frontend as a separate repo: https://github.com/Unleash/unleash-frontend. Total rewrite of UI using react + redux + material Design.
- Unleash moved to its own organization: https://github.com/Unleash making it more open and allow everyone to contribute.
- Unleash-docker as a separate module: https://github.com/Unleash/unleash-docker
- Unleash binary, making it easy to install and use Unleash as a service.
- Unleash-frontend as a separate repo: https://github.com/Unleash/unleash-frontend. Total rewrite of UI using react + redux + material Design.
- Unleash moved to its own organization: https://github.com/Unleash making it more open and allow everyone to contribute.
- Unleash-docker as a separate module: https://github.com/Unleash/unleash-docker
- Unleash binary, making it easy to install and use Unleash as a service.
- Removed all config/tuning that was specific to FINN.no usage of Unleash.
**If you are migrating from 1.0.0 to 2.0.0 we recommend reading [the migration guide](https://github.com/Unleash/unleash/blob/master/docs/migration-guide.md)**
## 1.0.0 (January 2015)
- Initial public release
- Initial public release

View File

@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at unleash@finn.no. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at unleash@finn.no. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

View File

@ -1,51 +1,46 @@
# Unleash
[![Build Status](https://travis-ci.org/Unleash/unleash.svg?branch=master)](https://travis-ci.org/Unleash/unleash)
[![Coverage Status](https://coveralls.io/repos/github/Unleash/unleash/badge.svg?branch=master)](https://coveralls.io/github/Unleash/unleash?branch=master)
[![Dependency Status](https://david-dm.org/Unleash/unleash.svg)](https://david-dm.org/Unleash/unleash)
[![devDependency Status](https://david-dm.org/Unleash/unleash/dev-status.svg)](https://david-dm.org/Unleash/unleash?type=dev)
[![Greenkeeper badge](https://badges.greenkeeper.io/Unleash/unleash.svg)](https://greenkeeper.io/)
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
[![Build Status](https://travis-ci.org/Unleash/unleash.svg?branch=master)](https://travis-ci.org/Unleash/unleash) [![Coverage Status](https://coveralls.io/repos/github/Unleash/unleash/badge.svg?branch=master)](https://coveralls.io/github/Unleash/unleash?branch=master) [![Dependency Status](https://david-dm.org/Unleash/unleash.svg)](https://david-dm.org/Unleash/unleash) [![devDependency Status](https://david-dm.org/Unleash/unleash/dev-status.svg)](https://david-dm.org/Unleash/unleash?type=dev) [![Greenkeeper badge](https://badges.greenkeeper.io/Unleash/unleash.svg)](https://greenkeeper.io/) [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
Unleash is a feature toggle system, that gives you a great overview over all feature toggles across
all your applications and services. It comes with official client implementations for Java, Node.js, Go and Ruby.
Unleash is a feature toggle system, that gives you a great overview over all feature toggles across all your applications and services. It comes with official client implementations for Java, Node.js, Go and Ruby.
The main motivation for doing feature toggling is to decouple the process for deploying code to production
and releasing new features. This helps reducing risk, and allow us to easily manage which features to enable
The main motivation for doing feature toggling is to decouple the process for deploying code to production and releasing new features. This helps reducing risk, and allow us to easily manage which features to enable
> Feature toggles decouple **deployment** of code from **release** of new features
This repo contains the unleash-server, which contains the admin UI and a place to ask for the status of features.
In order to make use of unleash you will also need a client implementation.
This repo contains the unleash-server, which contains the admin UI and a place to ask for the status of features. In order to make use of unleash you will also need a client implementation.
<img src="https://github.com/Unleash/unleash/raw/master/docs/assets/dashboard.png" alt="Unleash UI" width="600" />
[Online demo version available on heroku](https://unleash.herokuapp.com/#/features).
## Activation strategies
It's fine to have a system for turning stuff on and off. But some times we want more granular control,
we want to decide who to the toggle should be enabled for. This is where activation strategies comes in to
the picture. Activation strategies take arbitrary config and allows us to enable a toggle in various ways.
It's fine to have a system for turning stuff on and off. But some times we want more granular control, we want to decide who to the toggle should be enabled for. This is where activation strategies comes in to the picture. Activation strategies take arbitrary config and allows us to enable a toggle in various ways.
Common activation strategies includes:
- Active For users with a specified userId
- GradualRollout to X-percent of our users
- Active for our beta users
- Active only for application instances running on host x.
- Active only for application instances running on host x.
Read more about activation strategies in [docs/activation-strategies.md](./docs/activation-strategies.md)
## Client implementations
We have offical SDK's for Java, Node.js, Go, Ruby and Python. And we will be happy to add implementations in other langugages written by you! These libraries makes it very easy to use Unleash in you application.
Official client SDKs:
Official client SDKs:
- [unleash/unleash-client-java](https://github.com/unleash/unleash-client-java)
- [unleash/unleash-client-node](https://github.com/unleash/unleash-client-node)
- [unleash/unleash-client-go](https://github.com/unleash/unleash-client-go)
- [unleash/unleash-client-ruby](https://github.com/unleash/unleash-client-ruby)
- [unleash/unleash-client-python](https://github.com/Unleash/unleash-client-python)
Clients written by awesome enthusiasts: :fire:
Clients written by awesome enthusiasts: :fire:
- [stiano/unleash-client-dotnet](https://github.com/stiano/unleash-client-dotnet) (.Net Core)
- [onybo/unleash-client-core](https://github.com/onybo/unleash-client-core) (.Net Core)
- [rarruda/unleash-client-python](https://github.com/rarruda/unleash-client-python) (Python 3)
@ -62,22 +57,19 @@ if (unleash.isEnabled("AwesomeFeature")) {
}
```
# Running Unleash
# Running Unleash
## Requirements
You will need a __PostgreSQL__ 9.3+ database instance to be able to run Unleash.
You will need a **PostgreSQL** 9.3+ database instance to be able to run Unleash.
When starting Unleash you must specify a database URI (can be set as environment variable DATABASE_URL)
which includes a username and password, which has the rights to migrate the database.
When starting Unleash you must specify a database URI (can be set as environment variable DATABASE_URL) which includes a username and password, which has the rights to migrate the database.
_Unleash_ will, at startup, check whether database migration is needed, and perform necessary migrations.
## Using Unleash
## Using Unleash
**The simplest way to get started:**
(database-url can also be set as a environment variable: DATABASE_URL)
**The simplest way to get started:** (database-url can also be set as a environment variable: DATABASE_URL)
```bash
$ npm install unleash-server -g
@ -89,16 +81,19 @@ Unleash started on http://localhost:4242
You can also require Unleash as a lib (recommended) and expand it with more options. Read more about this feature in the [getting started guide](./docs/getting-started.md).
### Securing Unleash
Unleash also have extension points where you can integrate Unleash with your authentication provider (OAuth 2.0). Read more about [securing unleash](./docs/securing-unleash.md).
## Run with docker
We have made a separate project which runs unleash inside docker. Please see [unleash-docker](https://github.com/Unleash/unleash-docker)
# Developer Guide
If you want to contribute to this project you are encouraged to send issue request, or provide pull-requests.
Please read the [unleash developer guide](./docs/developer-guide.md) to learn more on how you can contribute.
If you want to contribute to this project you are encouraged to send issue request, or provide pull-requests. Please read the [unleash developer guide](./docs/developer-guide.md) to learn more on how you can contribute.
# I want to learn more
- [Blog: Unleash your features gradually!](http://bytes.schibsted.com/unleash-features-gradually/)
- [Presentation: Unleash your features gradually!](http://ivarconr.github.io/feature-toggles-presentation/sch-dev-lunch-2017/#1)
- http://martinfowler.com/bliki/FeatureToggle.html

View File

@ -1,15 +1,15 @@
{
"name": "Unleash",
"description": "A default setup of Unleash",
"repository": "https://github.com/heroku/node-js-sample",
"logo": "https://github.com/Unleash/unleash/blob/master/docs/assets/logo.png?raw=true",
"keywords": ["node", "feature toggles", "release"],
"addons": [
{
"plan": "heroku-postgresql",
"options": {
"version": "9.5"
}
}
]
}
"name": "Unleash",
"description": "A default setup of Unleash",
"repository": "https://github.com/heroku/node-js-sample",
"logo": "https://github.com/Unleash/unleash/blob/master/docs/assets/logo.png?raw=true",
"keywords": ["node", "feature toggles", "release"],
"addons": [
{
"plan": "heroku-postgresql",
"options": {
"version": "9.5"
}
}
]
}

View File

@ -3,67 +3,66 @@ id: activation_strategy
title: Activation Strategies
---
It is powerful to be able to turn a feature on and off instantaneously, without redeploying the application. The next level of control comes when you are able to enable a feature for specific users or enable it for a small subset of the users. We achieve this level of control with the help of activation strategies. The most simple strategy is the “default” strategy, which basically means that the feature should be enabled to everyone.
The definition of an activation strategy lives in the Unleash API and can be created via the Unleash UI. The implementation of activation strategies lives in the various client implementations.
The definition of an activation strategy lives in the Unleash API and can be created via the Unleash UI. The implementation of activation strategies lives in the various client implementations.
Unleash comes with a few common activation strategies. Some of them require the client to provide the [unleash-context](./unleash-context.md), which gives necessary context for unleash.
Unleash comes with a few common activation strategies. Some of them require the client to provide the [unleash-context](./unleash-context.md), which gives necessary context for unleash.
## default
It is the simplest activation strategy and basically means "active for everyone".
## userWithId
Active for users with a userId defined in the userIds-list. Typically I want to enable a new feature only for myself in production, before I enable it for everyone else. To achieve this we can use the “UserWithIdStrategy”. This strategy allows you to specify a list of user ids that you want to expose the new feature for. (A user id may of course be an email if that is more appropriate in your system.)
**Parameters**
- userIds - *List of user ids you want the feature toggle be enabled for*
- userIds - _List of user ids you want the feature toggle be enabled for_
## gradualRolloutUserId
Gradually activates feature toggle for logged in users. Stickiness based on the user id.
This strategy guarantees that the same user gets the same experience every time,
across devices. It also guarantees that a user which is among the first 10% will
also be among the first 20% of the users. Thus we ensure that users get the same
experience. Even if we gradually increase the number of users who are exposed to
a particular feature. To achieve this we hash the user id and normalise the hash
value to a number between 1 and 100 with a simple modulo operator.
Gradually activates feature toggle for logged in users. Stickiness based on the user id. This strategy guarantees that the same user gets the same experience every time, across devices. It also guarantees that a user which is among the first 10% will also be among the first 20% of the users. Thus we ensure that users get the same experience. Even if we gradually increase the number of users who are exposed to a particular feature. To achieve this we hash the user id and normalise the hash value to a number between 1 and 100 with a simple modulo operator.
![hash_and_normalise](assets/hash_and_normalise.png)
Starting from v3.x all clients should use the 32-bit [MurmurHash3](https://en.wikipedia.org/wiki/MurmurHash) algorithm to normalize values.
([issue 247](https://github.com/Unleash/unleash/issues/247))
Starting from v3.x all clients should use the 32-bit [MurmurHash3](https://en.wikipedia.org/wiki/MurmurHash) algorithm to normalize values. ([issue 247](https://github.com/Unleash/unleash/issues/247))
**Parameters**
- percentage - *The percentage (0-100) you want to enable the feature toggle for.*
- groupId - *Used to define an activation group, which allows you to correlate rollout across feature toggles.*
- percentage - _The percentage (0-100) you want to enable the feature toggle for._
- groupId - _Used to define an activation group, which allows you to correlate rollout across feature toggles._
## gradualRolloutSessionId
Gradually activates feature toggle. Stickiness based on session id. It is almost
identical to the `gradualRolloutUserId` strategy, with the exception that it works
on session ids. This makes it possible to target all users (not just logged in
users), guaranteeing that a user will get the same experience within a session.
Gradually activates feature toggle. Stickiness based on session id. It is almost identical to the `gradualRolloutUserId` strategy, with the exception that it works on session ids. This makes it possible to target all users (not just logged in users), guaranteeing that a user will get the same experience within a session.
**Parameters**
- percentage - *The percentage (0-100) you want to enable the feature toggle for.*
- groupId - *Used to define an activation group, which allows you to correlate rollout across feature toggles.*
## gradualRolloutRandom
Randomly activates the feature toggle. No stickiness. We have found this rollout strategy
very useful in some scenarios, especially when we enable a feature which is not
visible to the user. It is also the strategy we use to sample metrics and error reports.
- percentage - _The percentage (0-100) you want to enable the feature toggle for._
- groupId - _Used to define an activation group, which allows you to correlate rollout across feature toggles._
## gradualRolloutRandom
Randomly activates the feature toggle. No stickiness. We have found this rollout strategy very useful in some scenarios, especially when we enable a feature which is not visible to the user. It is also the strategy we use to sample metrics and error reports.
**Parameters**
- percentage - *The percentage (0-100) you want to enable the feature toggle for.*
- percentage - _The percentage (0-100) you want to enable the feature toggle for._
## remoteAddress
Active for remote addresses defined in the IPs list. We sometimes use this strategy to
enable a feature only for IP's in our office network.
Active for remote addresses defined in the IPs list. We sometimes use this strategy to enable a feature only for IP's in our office network.
**Parameters**
- IPS - *List of IPs to enable the feature for.*
- IPS - _List of IPs to enable the feature for._
## applicationHostname
Active for client instances with a hostName in the hostNames-list.
**Parameters**
- hostNames - *List of hostnames to enable the feature toggle for.*
- hostNames - _List of hostnames to enable the feature toggle for._

View File

@ -20,26 +20,24 @@ Defined event types:
**Response**
```json
```json
{
"version": 1,
"events":[
{
"id":454,
"type":"feature-updated",
"createdBy":"unknown",
"createdAt":"2016-08-24T11:22:01.354Z",
"data": {
"name":"eid.bankid.mobile",
"description":"",
"strategy":"default",
"enabled":true,
"parameters":{}
},
"diffs": [
{"kind":"E","path":["enabled"],"lhs":false,"rhs":true}
]
}
]
"version": 1,
"events": [
{
"id": 454,
"type": "feature-updated",
"createdBy": "unknown",
"createdAt": "2016-08-24T11:22:01.354Z",
"data": {
"name": "eid.bankid.mobile",
"description": "",
"strategy": "default",
"enabled": true,
"parameters": {}
},
"diffs": [{ "kind": "E", "path": ["enabled"], "lhs": false, "rhs": true }]
}
]
}
```

View File

@ -7,12 +7,10 @@ title: /api/admin/features
`GET: http://unleash.host.com/api/admin/features`
This endpoint is the one all admin ui should use to fetch all available feature toggles
from the _unleash-server_. The response returns all active feature toggles and their
current strategy configuration. A feature toggle will have _at least_ one configured strategy.
A strategy will have a `name` and `parameters` map.
This endpoint is the one all admin ui should use to fetch all available feature toggles from the _unleash-server_. The response returns all active feature toggles and their current strategy configuration. A feature toggle will have _at least_ one configured strategy. A strategy will have a `name` and `parameters` map.
**Example response:**
```json
{
"version": 2,
@ -53,8 +51,7 @@ A strategy will have a `name` and `parameters` map.
`GET: http://unleash.host.com/api/admin/features/:featureName`
Used to fetch details about a specific featureToggle. This is mostly provded to make it easy to
debug the API and should not be used by the client implementations.
Used to fetch details about a specific featureToggle. This is mostly provded to make it easy to debug the API and should not be used by the client implementations.
```json
{
@ -70,13 +67,13 @@ debug the API and should not be used by the client implementations.
}
```
### Create a new Feature Toggle
`POST: http://unleash.host.com/api/admin/features/`
**Body:**
```json
```json
{
"name": "Feature.A",
"description": "lorem ipsum..",
@ -90,17 +87,17 @@ debug the API and should not be used by the client implementations.
}
```
Used by the admin-dashboard to create a new feature toggles. The name **must be unique**,
otherwise you will get a _403-response_.
Used by the admin-dashboard to create a new feature toggles. The name **must be unique**, otherwise you will get a _403-response_.
Returns 200-respose if the feature toggle was created successfully.
Returns 200-respose if the feature toggle was created successfully.
### Update a Feature Toggle
`PUT: http://unleash.host.com/api/admin/features/:toggleName`
**Body:**
```json
```json
{
"name": "Feature.A",
"description": "lorem ipsum..",
@ -114,18 +111,15 @@ Returns 200-respose if the feature toggle was created successfully.
}
```
Used by the admin dashboard to update a feature toggles. The name has to match an
existing features toggle.
Used by the admin dashboard to update a feature toggles. The name has to match an existing features toggle.
Returns 200-respose if the feature toggle was updated successfully.
Returns 200-respose if the feature toggle was updated successfully.
### Archive a Feature Toggle
`DELETE: http://unleash.host.com/api/admin/features/:toggleName`
Used to archive a feature toggle. A feature toggle can never be totally be deleted,
but can be archived. This is a design decision to make sure that a old feature
toggle suddenly reappears becuase someone else re-using the same name.
Used to archive a feature toggle. A feature toggle can never be totally be deleted, but can be archived. This is a design decision to make sure that a old feature toggle suddenly reappears becuase someone else re-using the same name.
## Archive
@ -136,6 +130,7 @@ toggle suddenly reappears becuase someone else re-using the same name.
Used to fetch list of archived feature toggles
**Example response:**
```json
{
"version": 1,
@ -162,10 +157,11 @@ Used to fetch list of archived feature toggles
`POST http://unleash.host.com/api/admin/archive/revive`
**Body:**
```json
```json
{
"name": "Feature.A"
}
```
Used to revive a feature toggle.
Used to revive a feature toggle.

View File

@ -5,36 +5,24 @@ title: /api/admin/metrics
# This document describes the metrics endpoint for admin ui
### Seen-toggles
`GET http://unleash.host.com/api/admin/seen-toggles`
This enpoints returns a list of applications and what toogles
unleash has seend for each application. It will only guarantee
toggles reported by client applications within the last hour, but
will in most cases remember seen-toggles for applications longer
This enpoints returns a list of applications and what toogles unleash has seend for each application. It will only guarantee toggles reported by client applications within the last hour, but will in most cases remember seen-toggles for applications longer
**Example response:**
**Example response:**
```json
[
{
"appName": "demo-app",
"seenToggles": [
"add-feature-2",
"toggle-2",
"toggle-3"
],
"seenToggles": ["add-feature-2", "toggle-2", "toggle-3"],
"metricsCount": 127
},
{
"appName": "demo-app-2",
"seenToggles": [
"add-feature-2",
"toggle-2",
"toggle-3"
],
"seenToggles": ["add-feature-2", "toggle-2", "toggle-3"],
"metricsCount": 21
}
]
@ -42,22 +30,17 @@ will in most cases remember seen-toggles for applications longer
**Fields:**
* **appName** - Name of the application seen by unleash-server
* **seenToggles** - array of toggles names seen by unleash-server for this application
* **metricsCount** - number of metrics counted across all toggles for this application.
- **appName** - Name of the application seen by unleash-server
- **seenToggles** - array of toggles names seen by unleash-server for this application
- **metricsCount** - number of metrics counted across all toggles for this application.
### Feature-Toggles metrics
`GET http://unleash.host.com/api/admin/metrics/feature-toggles`
This endpoint gives _last minute_ and _last hour_ metrics for all active toggles. This is based on
metrics reported by client applications. Yes is the number of times a given feature toggle
was evaluated to enabled in a client applcation, and no is the number it avaluated to false.
This endpoint gives _last minute_ and _last hour_ metrics for all active toggles. This is based on metrics reported by client applications. Yes is the number of times a given feature toggle was evaluated to enabled in a client applcation, and no is the number it avaluated to false.
**Example response:**
**Example response:**
```json
{
@ -94,28 +77,21 @@ was evaluated to enabled in a client applcation, and no is the number it avaluat
**Fields:**
* **lastHour** - Hour projection collected metrics for all feature toggles.
* **lastMinute** - Mintue projection collected metrics for all feature toggles.
- **lastHour** - Hour projection collected metrics for all feature toggles.
- **lastMinute** - Mintue projection collected metrics for all feature toggles.
### Applications
`GET http://unleash.host.com/api/admin/applications`
This endpoint returns a list of known applications (seen the last two days) and
a link to follow for more datails.
`GET http://unleash.host.com/api/admin/applications`
This endpoint returns a list of known applications (seen the last two days) and a link to follow for more datails.
```json
{
"applications": [
{
"appName": "another",
"strategies": [
"default",
"other",
"brother"
],
"strategies": ["default", "other", "brother"],
"createdAt": "2016-12-09T14:56:36.730Z",
"links": {
"appDetails": "/api/admin/applications/another"
@ -123,11 +99,7 @@ a link to follow for more datails.
},
{
"appName": "bow",
"strategies": [
"default",
"other",
"brother"
],
"strategies": ["default", "other", "brother"],
"createdAt": "2016-12-09T14:56:36.730Z",
"links": {
"appDetails": "/api/admin/applications/bow"
@ -138,23 +110,16 @@ a link to follow for more datails.
```
#### Query Params
You can also specify the query param: _strategyName_, which will return all applications
implementing the given strategy.
`GET http://unleash.host.com/api/admin/applications?strategyName=someStrategyName`
You can also specify the query param: _strategyName_, which will return all applications implementing the given strategy.
`GET http://unleash.host.com/api/admin/applications?strategyName=someStrategyName`
### Application Details
`GET http://unleash.host.com/api/admin/applications/:appName`
This endpoint gives insight into details about a client applcation, such as instances,
strategies implemented and seen toogles.
`GET http://unleash.host.com/api/admin/applications/:appName`
This endpoint gives insight into details about a client applcation, such as instances, strategies implemented and seen toogles.
```json
{
@ -171,32 +136,24 @@ strategies implemented and seen toogles.
"clientIp": "::ffff:127.0.0.1",
"lastSeen": "2016-11-30T16:04:15.991Z",
"createdAt": "2016-11-30T10:49:11.223Z"
},
}
],
"strategies": [
{
"appName": "demo-app",
"strategies": [
"default",
"extra"
]
"strategies": ["default", "extra"]
}
],
"seenToggles": [
"add-feature-2",
"toggle-2",
"toggle-3"
]
"seenToggles": ["add-feature-2", "toggle-2", "toggle-3"]
}
```
### Seen applications
`GET http://unleash.host.com/api/admin/seen-apps`
`GET http://unleash.host.com/api/admin/seen-apps`
This endpoint gives insight into details about application seen per feature toggle.
```json
{
"my-toggle": [
@ -225,9 +182,7 @@ This endpoint gives insight into details about application seen per feature togg
"createdAt": "2016-12-28T10:39:24.966Z",
"updatedAt": "2017-01-06T15:32:41.932Z",
"description": "our other app",
"strategies": [
"default",
],
"strategies": ["default"],
"url": "http://example.com",
"color": null,
"icon": "desktop"

View File

@ -3,53 +3,55 @@ id: strategies
title: /api/admin/strategies
---
### Fetch Strategies
### Fetch Strategies
`GET: http://unleash.host.com/api/admin/strategies`
Used to fetch all defined strategies and their defined paramters.
Used to fetch all defined strategies and their defined paramters.
**Response**
```json
```json
{
"version": 1,
"strategies": [
"version": 1,
"strategies": [
{
"name": "default",
"description": "Default on/off strategy.",
"parameters": []
},
{
"name": "userWithId",
"description": "Active for userId specified in the comma seperated 'userIds' parameter.",
"parameters": [
{
"name": "default",
"description": "Default on/off strategy.",
"parameters": []
"name": "userIds",
"type": "list",
"description": "List of unique userIds the feature should be active for.",
"required": true
}
]
},
{
"name": "gradualRollout",
"description": "Gradual rollout to logged in users",
"parameters": [
{
"name": "percentage",
"type": "percentage",
"description": "How many percent should the new feature be active for.",
"required": false
},
{
"name": "userWithId",
"description": "Active for userId specified in the comma seperated 'userIds' parameter.",
"parameters": [
{
"name": "userIds",
"type": "list",
"description": "List of unique userIds the feature should be active for.",
"required": true
}
]
},
{
"name": "gradualRollout",
"description": "Gradual rollout to logged in users",
"parameters": [
{
"name": "percentage",
"type": "percentage",
"description": "How many percent should the new feature be active for.",
"required": false
},
{
"name": "group",
"type": "string",
"description": "Group key to use when hasing the userId. Makes sure that the same user get different value for different groups",
"required": false
}
]
},
]}
"name": "group",
"type": "string",
"description": "Group key to use when hasing the userId. Makes sure that the same user get different value for different groups",
"required": false
}
]
}
]
}
```
### Create strategy
@ -79,8 +81,7 @@ Used to fetch all defined strategies and their defined paramters.
},
```
Used to create a new Strategy. Name is required and must be unique. It is also required to have a parameters array, but it can be empty.
Used to create a new Strategy. Name is required and must be unique. It is also required to have a parameters array, but it can be empty.
### Update strategy
@ -109,5 +110,4 @@ Used to create a new Strategy. Name is required and must be unique. It is also r
},
```
Used to update a Strategy definition. Name can't be changed.
**PS! I can be dangerous to change a implemnted strategy as the implementation also might need to be changed**
Used to update a Strategy definition. Name can't be changed. **PS! I can be dangerous to change a implemnted strategy as the implementation also might need to be changed**

View File

@ -9,23 +9,17 @@ title: /api/client/features
**HEADERS:**
* UNLEASH-APPNAME: appName
* UNLEASH-INSTANCEID: instanceId
- UNLEASH-APPNAME: appName
- UNLEASH-INSTANCEID: instanceId
This endpoint is the one all clients should use to fetch all available feature toggles
from the _unleash-server_. The response returns all active feature toggles and their
current strategy configuration. A feature toggle will have _at least_ one configured strategy.
A strategy will have a `name` and `parameters` map.
This endpoint is the one all clients should use to fetch all available feature toggles from the _unleash-server_. The response returns all active feature toggles and their current strategy configuration. A feature toggle will have _at least_ one configured strategy. A strategy will have a `name` and `parameters` map.
> _Note:_ Clients should prefer the `strategies` property.
> Legacy properties (`strategy` & `parameters`) will be kept until **version 2** of the format.
> _Note:_ Clients should prefer the `strategies` property. Legacy properties (`strategy` & `parameters`) will be kept until **version 2** of the format.
This endpoint should never return anything besides a valid *20X or 304-response*. It will also
include an `Etag`-header. The value of this header can be used by clients as the value of
the `If-None-Match`-header in the request to prevent a data transfer if the client already
has the latest response locally.
This endpoint should never return anything besides a valid _20X or 304-response_. It will also include an `Etag`-header. The value of this header can be used by clients as the value of the `If-None-Match`-header in the request to prevent a data transfer if the client already has the latest response locally.
**Example response:**
```json
{
"version": 1,
@ -70,15 +64,13 @@ has the latest response locally.
}
```
You may limit the response by sending a `namePrefix` query-parameter.
You may limit the response by sending a `namePrefix` query-parameter.
`GET: http://unleash.host.com/api/client/features/:featureName`
Used to fetch details about a specific feature toggle. This is mainly provided to make it easy to
debug the API and should not be used by the client implementations.
Used to fetch details about a specific feature toggle. This is mainly provided to make it easy to debug the API and should not be used by the client implementations.
> _Notice_: You will not get a version property when fetching a specific feature toggle by name.
> _Notice_: You will not get a version property when fetching a specific feature toggle by name.
```json
{

View File

@ -7,25 +7,25 @@ title: /api/client/metrics
`POST: http://unleash.host.com/api/client/metrics`
Register a metrics payload with a timed bucket.
Register a metrics payload with a timed bucket.
```json
{
"appName": "appName",
"instanceId": "instanceId",
"bucket": {
"start": "2016-11-03T07:16:43.572Z",
"stop": "2016-11-03T07:16:53.572Z",
"toggles": {
"toggle-name-1": {
"yes": 123,
"no": 321
},
"toggle-name-2": {
"yes": 111,
"no": 0
}
}
"appName": "appName",
"instanceId": "instanceId",
"bucket": {
"start": "2016-11-03T07:16:43.572Z",
"stop": "2016-11-03T07:16:53.572Z",
"toggles": {
"toggle-name-1": {
"yes": 123,
"no": 321
},
"toggle-name-2": {
"yes": 111,
"no": 0
}
}
}
}
```

View File

@ -7,25 +7,24 @@ title: /api/client/register
`POST: http://unleash.host.com/api/client/register`
Registers a client instance with the unleash server. The client should send all fields specified.
Registers a client instance with the unleash server. The client should send all fields specified.
```json
{
"appName": "appName",
"instanceId": "instanceId",
"sdkVersion": "unleash-client-java:2.2.0",
"strategies": ["default", "some-strategy-1"],
"started": "2016-11-03T07:16:43.572Z",
"interval": 10000
"appName": "appName",
"instanceId": "instanceId",
"sdkVersion": "unleash-client-java:2.2.0",
"strategies": ["default", "some-strategy-1"],
"started": "2016-11-03T07:16:43.572Z",
"interval": 10000
}
```
**Fields:**
* **appName** - Name of the application seen by unleash-server
* **instanceId** - Instance id for this application (typically hostname, podId or similar)
* **sdkVersion** - Optional field that describes the sdk version (name:version)
* **strategies** - List of strategies implemented by this application
* **started** - When this client started. Should be reported as [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) time.
* **interval** - At which interval, in milliseconds, will this client be expected to send metrics
- **appName** - Name of the application seen by unleash-server
- **instanceId** - Instance id for this application (typically hostname, podId or similar)
- **sdkVersion** - Optional field that describes the sdk version (name:version)
- **strategies** - List of strategies implemented by this application
- **started** - When this client started. Should be reported as [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) time.
- **interval** - At which interval, in milliseconds, will this client be expected to send metrics

View File

@ -4,19 +4,22 @@ title: API Documentation
---
## Client API
This describes the API provided to unleash-clients.
* [Feature Toggles API](client/feature-toggles-api.md)
* [Register API](client/register-api.md)
* [Metrics API](client/metrics-api.md)
This describes the API provided to unleash-clients.
- [Feature Toggles API](client/feature-toggles-api.md)
- [Register API](client/register-api.md)
- [Metrics API](client/metrics-api.md)
## Admin API (internal)
The internal API used by the Admin UI (unleash-frontend):
* [Feature Toggles API](admin/feature-toggles-api.md)
* [Strategies API](admin/strategies-api.md)
* [Events API](admin/events-api.md)
* [Metrics API](admin/metrics-api.md)
- [Feature Toggles API](admin/feature-toggles-api.md)
- [Strategies API](admin/strategies-api.md)
- [Events API](admin/events-api.md)
- [Metrics API](admin/metrics-api.md)
## System API's
* [Internal Backstage API](internal-backstage-api.md)
- [Internal Backstage API](internal-backstage-api.md)

View File

@ -7,18 +7,16 @@ title: /internal-backstage/prometheus
`GET http://unleash.host.com/internal-backstage/prometheus`
Unleash uses prometheus internally to collect metrics. These are
available on the given url if the `serverMetrics` option is enabled (default=true).
Unleash uses prometheus internally to collect metrics. These are available on the given url if the `serverMetrics` option is enabled (default=true).
[Read more about Prometheus](https://prometheus.io/)
[Read more about Prometheus](https://prometheus.io/)
## Annotations
Unleash will automatically count all updates for all toggles under the metric name `feature_toggle_update_total`, and the toggle name is will be set as a label value. This information can be used to create annotations in grafana for everytime a feature toggle is changed.
Unleash will automatically count all updates for all toggles under the metric name `feature_toggle_update_total`, and the toggle name is will be set as a label value. This information can be used to create annotations in grafana for everytime a feature toggle is changed.
You can use this query in grafana to achive this:
```
delta(feature_toggle_update_total{toggle="Demo"}[1m]) != bool 0?
```

View File

@ -3,137 +3,115 @@ id: client_specification
title: Client Specification
---
# Client Specification 1.0
This document attempts to guide developers in implementing a Unleash Client SDK.
This document attempts to guide developers in implementing a Unleash Client SDK.
## System Overview
Unleash is comprised of three parts:
- **Unleash API** - The service holding all feature toggles and their configurations. Configurations declare which activation strategies to use and which parameters they should get.
- **Unleash UI** - The dashboard used to manage feature toggles, define new strategies, look at metrics, etc.
- **Unleash SDK** - Used by clients to check if a feature is enabled or disabled. The SDK also collects metrics and sends them to the Unleash API. Activation Strategies are also implemented in the SDK. Unleash currently provides official SDKs for Java and Node.js
![system_overview](https://raw.githubusercontent.com/Unleash/unleash/master/docs/assets/unleash-diagram.png "System Overview")
![system_overview](https://raw.githubusercontent.com/Unleash/unleash/master/docs/assets/unleash-diagram.png 'System Overview')
In order to be super fast, the client SDK caches all feature toggles and their current configuration in memory. The activation strategies are also implemented in the SDK. This makes it really fast to check if a toggle is on or off because it is just a simple function operating on local state, without the need to poll data from the database.
## The Basics
All client implementations should strive to have a simple and consistent user API.
It should be a simple method, called isEnabled, to check if a feature toggle is enabled
or not. The method should return a `boolean` value, true or false.
All client implementations should strive to have a simple and consistent user API. It should be a simple method, called isEnabled, to check if a feature toggle is enabled or not. The method should return a `boolean` value, true or false.
```javascript
unleash.isEnabled("myAwesomeToggle")
unleash.isEnabled('myAwesomeToggle');
```
The basic `isEnabled` method should also accept a default value. This should be used if
the client does not know anything about that that toggle name. If the user does not specify
a default value, false should be returned for unknown feature toggles.
The basic `isEnabled` method should also accept a default value. This should be used if the client does not know anything about that that toggle name. If the user does not specify a default value, false should be returned for unknown feature toggles.
**Calling unleash with default value:**
```javascript
```javascript
boolean value = unleash.isEnabled("unknownFeatureToggle", false);
//value==false because default value was used.
//value==false because default value was used.
```
### Implementation of isEnabled
A feature toggle is defined as:
A feature toggle is defined as:
```json
{
"name": "Feature.B",
"description": "lorem ipsum",
"enabled": true,
"strategies": [
{
"name": "ActiveForUserWithId",
"parameters": {
"userIdList": "123,221,998"
}
},
{
"name": "GradualRolloutRandom",
"parameters": {
"percentage": "10"
}
}
],
"strategy": "ActiveForUserWithId",
"name": "Feature.B",
"description": "lorem ipsum",
"enabled": true,
"strategies": [
{
"name": "ActiveForUserWithId",
"parameters": {
"userIdList": "123,221,998"
}
},
{
"name": "GradualRolloutRandom",
"parameters": {
"percentage": "10"
}
}
],
"strategy": "ActiveForUserWithId",
"parameters": {
"userIdList": "123,221,998"
}
}
```
A simple demo of the isEnable function in JavaScript-style (most implementation will probably be more functional):
```javascript
function isEnabled(name, unleashContext = {}, defaultValue = false) {
const toggle = toggleRepository.get(name);
let enabled = false;
if ( !toggle ) {
return defaultValue;
} else if ( ! toggle.isEnabled) {
return false;
} else {
for(let i=0;i<toggle.strategies.length;i++) {
let strategyDef = toggle.strategies[i];
let strategyImpl = strategyImplRepository.get(strategyDef.name);
if(strategyImpl.isEnabled(toggle.parameters, unleashContext)) {
return true;
}
}
return false;
const toggle = toggleRepository.get(name);
let enabled = false;
if (!toggle) {
return defaultValue;
} else if (!toggle.isEnabled) {
return false;
} else {
for (let i = 0; i < toggle.strategies.length; i++) {
let strategyDef = toggle.strategies[i];
let strategyImpl = strategyImplRepository.get(strategyDef.name);
if (strategyImpl.isEnabled(toggle.parameters, unleashContext)) {
return true;
}
}
return false;
}
}
```
## Activation Strategies
Activation strategies are defined and configured in the unleash-service. It is up to the client
to provide the actual implementation of each activation strategy.
Unleash also ships with a few built-in strategies and it is expected that client SDK's implement
these. Read more about these [activation strategies](activation-strategies.md). For the built-in
strategies to work as expected the client should also allow the user to define a
[unleash-context](unleash-context.md). The context should be possible to pass in as part of
the `isEnabled` call.
Activation strategies are defined and configured in the unleash-service. It is up to the client to provide the actual implementation of each activation strategy.
Unleash also ships with a few built-in strategies and it is expected that client SDK's implement these. Read more about these [activation strategies](activation-strategies.md). For the built-in strategies to work as expected the client should also allow the user to define a [unleash-context](unleash-context.md). The context should be possible to pass in as part of the `isEnabled` call.
### Extension points
Client implementation should also provide a defined interface to make it easier for
the user to implement their own activation strategies, and register those in the unleash client.
Client implementation should also provide a defined interface to make it easier for the user to implement their own activation strategies, and register those in the unleash client.
## Fetching feature toggles (polling)
The client implementation should fetch toggles in the background, as regular polling.
In thread based environment (e.g. Java) this needs to be done on a separate thread.
The default poll interval should be **15 seconds**, and it should be configurable.
The client implementation should fetch toggles in the background, as regular polling. In thread based environment (e.g. Java) this needs to be done on a separate thread. The default poll interval should be **15 seconds**, and it should be configurable.
## Client registration
Client implementation should at initialization register with the unleash-server.
The should send a registration as specified in the [api documentation](api/client/register-api.md).
The registration must include all fields specified.
Client implementation should at initialization register with the unleash-server. The should send a registration as specified in the [api documentation](api/client/register-api.md). The registration must include all fields specified.
## Metrics
Clients are expected to send metrics back to Unleash API at regular intervals. The metrics is a list
of used toggles and how many times they evaluated to *yes* or *no* in the current period.
Read more about how to send the metrics in the [metrics-api](api/client/metrics-api.md) documentation.
Clients are expected to send metrics back to Unleash API at regular intervals. The metrics is a list of used toggles and how many times they evaluated to _yes_ or _no_ in the current period. Read more about how to send the metrics in the [metrics-api](api/client/metrics-api.md) documentation.
## Backup Feature Toggles
The SDK also persists the latest known state to a local file at the instance where the client is running.
It will persist a local copy every time the client detects changes from the API. Having a local backup of
the latest known state minimises the consequence of clients not being able to to talk to Unleash API at
startup. This is required because network is unreliable.
The SDK also persists the latest known state to a local file at the instance where the client is running. It will persist a local copy every time the client detects changes from the API. Having a local backup of the latest known state minimises the consequence of clients not being able to to talk to Unleash API at startup. This is required because network is unreliable.

View File

@ -3,8 +3,7 @@ id: database_backup
title: Database Backup
---
When upgrading to a new major version of Unleash it is advised to do a
full database backup to ease rollback in case of failures.
When upgrading to a new major version of Unleash it is advised to do a full database backup to ease rollback in case of failures.
1. Create a database backup:

View File

@ -3,60 +3,56 @@ id: database_schema
title: Database Schema
---
This document describes our current database schema used in PostgreSQL.
We use db-migrate to migrate (create tables, add columns etc) the database.
This document describes our current database schema used in PostgreSQL. We use db-migrate to migrate (create tables, add columns etc) the database.
## Table: _migrations_
Used by db-migrate module to keep track of migrations.
Used by db-migrate module to keep track of migrations.
| NAME | TYPE | SIZE | NULLABLE | COLUMN_DEF |
| ----------- | --------- | ----------- | -------- | -------------------------------------- |
| id | serial | 10 | 0 | nextval('migrations_id_seq'::regclass) |
| name | varchar | 255 | 0 | (null) |
| run_on | timestamp | 29 | 0 | (null) |
| NAME | TYPE | SIZE | NULLABLE | COLUMN_DEF |
| ------ | --------- | ---- | -------- | -------------------------------------- |
| id | serial | 10 | 0 | nextval('migrations_id_seq'::regclass) |
| name | varchar | 255 | 0 | (null) |
| run_on | timestamp | 29 | 0 | (null) |
## Table: _events_
| NAME | TYPE | SIZE | NULLABLE | COLUMN_DEF |
| ----------- | --------- | ----------- | -------- | ---------------------------------- |
| id | serial | 10 | 0 | nextval('events_id_seq'::regclass) |
| created_at | timestamp | 29 | 1 | now() |
| type | varchar | 255 | 0 | (null) |
| created_by | varchar | 255 | 0 | (null) |
| data | json | 2147483647 | 1 | (null) |
| NAME | TYPE | SIZE | NULLABLE | COLUMN_DEF |
| ---------- | --------- | ---------- | -------- | ---------------------------------- |
| id | serial | 10 | 0 | nextval('events_id_seq'::regclass) |
| created_at | timestamp | 29 | 1 | now() |
| type | varchar | 255 | 0 | (null) |
| created_by | varchar | 255 | 0 | (null) |
| data | json | 2147483647 | 1 | (null) |
## Table: _strategies_
| NAME | TYPE | SIZE | NULLABLE | COLUMN_DEF |
| ------------------- | --------- | ----------- | -------- | ---------- |
| created_at | timestamp | 29 | 1 | now() |
| name | varchar | 255 | 0 | (null) |
| description | text | 2147483647 | 1 | (null) |
| parameters_template | json | 2147483647 | 1 | (null) |
| NAME | TYPE | SIZE | NULLABLE | COLUMN_DEF |
| ------------------- | --------- | ---------- | -------- | ---------- |
| created_at | timestamp | 29 | 1 | now() |
| name | varchar | 255 | 0 | (null) |
| description | text | 2147483647 | 1 | (null) |
| parameters_template | json | 2147483647 | 1 | (null) |
## Table: _features_
| **NAME** | **TYPE** | **SIZE** | **NULLABLE** | **COLUMN_DEF** | **COMMENT** |
| ------------- | --------- | ----------- | ------------ | -------------- | ----------- |
| created_at | timestamp | 29 | 1 | now() | |
| name | varchar | 255 | 0 | (null) | |
| enabled | int4 | 10 | 1 | 0 | |
| description | text | 2147483647 | 1 | (null) | |
| archived | int4 | 10 | 1 | 0 | |
| strategies | json | 2147483647 | 1 | (null) | |
| **NAME** | **TYPE** | **SIZE** | **NULLABLE** | **COLUMN_DEF** | **COMMENT** |
| ----------- | --------- | ---------- | ------------ | -------------- | ----------- |
| created_at | timestamp | 29 | 1 | now() | |
| name | varchar | 255 | 0 | (null) | |
| enabled | int4 | 10 | 1 | 0 | |
| description | text | 2147483647 | 1 | (null) | |
| archived | int4 | 10 | 1 | 0 | |
| strategies | json | 2147483647 | 1 | (null) | |
## Table: _client_strategies_
| COLUMN_NAME | TYPE_NAME | COLUMN_SIZE | NULLABLE | COLUMN_DEF |
| ----------- | --------- | ----------- | -------- | ---------- |
| app_name | varchar | 255 | 0 | (null) |
| updated_at | timestamp | 29 | 1 | now() |
| COLUMN_NAME | TYPE_NAME | COLUMN_SIZE | NULLABLE | COLUMN_DEF |
| ----------- | --------- | ----------- | -------- | ---------- |
| app_name | varchar | 255 | 0 | (null) |
| updated_at | timestamp | 29 | 1 | now() |
| strategies | json | 2147483647 | 1 | (null) |
## Table: _client_instances_
| COLUMN_NAME | TYPE_NAME | COLUMN_SIZE | NULLABLE | COLUMN_DEF |
@ -69,8 +65,8 @@ Used by db-migrate module to keep track of migrations.
## Table: _client_metrics_
| COLUMN_NAME | TYPE_NAME | COLUMN_SIZE | NULLABLE | COLUMN_DEF |
| ----------- | --------- | ----------- | -------- | ------------------------------------------ |
| id | serial | 10 | 0 | nextval('client_metrics_id_seq'::regclass) |
| created_at | timestamp | 29 | 1 | now() |
| metrics | json | 2147483647 | 1 | (null) |
| COLUMN_NAME | TYPE_NAME | COLUMN_SIZE | NULLABLE | COLUMN_DEF |
| ----------- | --------- | ----------- | -------- | ------------------------------------------ |
| id | serial | 10 | 0 | nextval('client_metrics_id_seq'::regclass) |
| created_at | timestamp | 29 | 1 | now() |
| metrics | json | 2147483647 | 1 | (null) |

View File

@ -3,10 +3,9 @@ id: developer_guide
title: Developer guide
---
## PostgreSQL
To run and develop unleash you need to have PostgreSQL database (PostgreSQL v.9.5.x or newer) locally.
To run and develop unleash you need to have PostgreSQL database (PostgreSQL v.9.5.x or newer) locally.
### Create a local unleash databases in postgres
@ -30,9 +29,8 @@ export TEST_DATABASE_URL=postgres://unleash_user:passord@localhost:5432/unleash_
```
## PostgreSQL with docker
If you dont want to install PostgreSQL locally you can spin up an instance with docker.
We have created a script to ease this process: `scripts/docker-postgres.sh`
If you dont want to install PostgreSQL locally you can spin up an instance with docker. We have created a script to ease this process: `scripts/docker-postgres.sh`
## Commands
@ -55,20 +53,21 @@ npm test
## Database changes
We use database migrations to track database changes.
We use database migrations to track database changes.
### Making a schema change
In order to run migrations you will set the environment variable for DATABASE_URL
`export DATABASE_URL=postgres://unleash_user:passord@localhost:5432/unleash`
Use db-migrate to create new migrations file.
Use db-migrate to create new migrations file.
```bash
> npm run db-migrate -- create YOUR-MIGRATION-NAME
```
All migrations require one `up` and one `down` method.
All migrations require one `up` and one `down` method.
Example of a typical migration:
@ -76,17 +75,21 @@ Example of a typical migration:
/* eslint camelcase: "off" */
'use strict';
exports.up = function (db, cb) {
db.createTable('examples', {
id: { type: 'int', primaryKey: true, notNull: true },
created_at: { type: 'timestamp', defaultValue: 'now()' },
}, cb);
exports.up = function(db, cb) {
db.createTable(
'examples',
{
id: { type: 'int', primaryKey: true, notNull: true },
created_at: { type: 'timestamp', defaultValue: 'now()' },
},
cb,
);
};
exports.down = function (db, cb) {
return db.dropTable('examples', cb);
exports.down = function(db, cb) {
return db.dropTable('examples', cb);
};
```
```
Test your migrations:
@ -95,11 +98,10 @@ Test your migrations:
> npm run db-migrate -- down
```
## Publishing / Releasing new packages
Please run `npm run nsp` nad `npm run test` checks before publishing.
Run `npm run publish` to start the publishing process.
`npm run publish:dry`
`npm run publish:dry`

View File

@ -5,14 +5,14 @@ title: Getting Started
## Requirements
You will need Node.js >= 8.0.0 and a __PostreSQL__ 9.5+ database instance to be able to run Unleash.
You will need Node.js >= 8.0.0 and a **PostreSQL** 9.5+ database instance to be able to run Unleash.
When starting Unleash you must specify a database uri (can be set as environment variable DATABASE_URL)
which includes a username and password, that have rights to migrate the database.
When starting Unleash you must specify a database uri (can be set as environment variable DATABASE_URL) which includes a username and password, that have rights to migrate the database.
On startup _Unleash_ will perform necessary migrations if needed.
## Start Unleash
## Start Unleash
### 1. The simplest way to get started:
```bash
@ -23,34 +23,40 @@ Unleash started on http://localhost:4242
```
### 2. Or programmatically:
You can also depend on unleash
```js
const unleash = require('unleash-server');
unleash.start({
databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
port: 4242
}).then(unleash => {
console.log(`Unleash started on http://localhost:${unleash.app.get('port')}`);
});
unleash
.start({
databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
port: 4242,
})
.then(unleash => {
console.log(
`Unleash started on http://localhost:${unleash.app.get('port')}`,
);
});
```
Available unleash options includes:
- **databaseUrl** - the postgress database url to connect to. Should include username/password.
- **databaseUrl** - the postgress database url to connect to. Should include username/password.
- **port** - Which port should the unleash-server bind to?
- **enableLegacyRoutes** (boolean) - allows you to turn on/off support for legacy routes to support older clients. Enabled by default.
- **serverMetrics** (boolean) - Use this option to turn off prometheus metrics.
- **preHook** (function) - This is a hook if you need to provide any middlewares to express before `unleash` adds any. Express app instance is injected as first arguement.
- **preRouterHook** (function) - Use this to register custom express middlewares before the `unleash` specific routers are added. This is typically how you would register custom middlewares to handle authentication.
- **secret** (string) - Set this when you want to secure unleash. Used to encrypt the user session.
- **serverMetrics** (boolean) - Use this option to turn off prometheus metrics.
- **preHook** (function) - This is a hook if you need to provide any middlewares to express before `unleash` adds any. Express app instance is injected as first arguement.
- **preRouterHook** (function) - Use this to register custom express middlewares before the `unleash` specific routers are added. This is typically how you would register custom middlewares to handle authentication.
- **secret** (string) - Set this when you want to secure unleash. Used to encrypt the user session.
- **adminAuthentication** (string) - Use this when implementing custom admin authentication [securing-unleash](./securing-unleash.md). Possible values are:
- `none` - Will disable authentication altogether
- `unsecure` - (default) Will use simple cookie based authentication. UI will require the user to specify an email in order to use unleash.
- `custom` - Use this when you implement your own custom authentication logic.
- `unsecure` - (default) Will use simple cookie based authentication. UI will require the user to specify an email in order to use unleash.
- `custom` - Use this when you implement your own custom authentication logic.
### 3. Docker
You can also use the [hosted docker image](https://hub.docker.com/r/unleashorg/unleash-server/) to start the Unleash server
```sh
@ -58,36 +64,36 @@ docker run -d -e DATABASE_URL=postgres://user:pass@10.200.221.11:5432/unleash un
```
## How do I configure the log output?
By default, `unleash` uses [log4js](https://github.com/nomiddlename/log4js-node) to log important information. It is possible to swap out the logger provider (only when using Unleash programmatically). This enables filtering of log levels and easy redirection of output streams.
### What is a logger provider?
A logger provider is a function which takes the name of a logger and returns a logger implementation. For instance, the following code snippet shows how a logger provider for the global `console` object could be written:
```javascript
function consoleLoggerProvider (name) {
function consoleLoggerProvider(name) {
// do something with the name
return {
debug: console.log,
info: console.log,
warn: console.log,
error: console.error
error: console.error,
};
}
```
The logger interface with its `debug`, `info`, `warn` and `error` methods expects format string support as seen in `debug` or the JavaScript `console` object. Many commonly used logging implementations cover this API, e.g. bunyan, pino or winston.
### How do I set a logger provider?
Custom logger providers need to be set *before requiring the `unleash-server` module*. The following example shows how this can be done:
Custom logger providers need to be set _before requiring the `unleash-server` module_. The following example shows how this can be done:
```javascript
// first configure the logger provider
const unleashLogger = require('unleash-server/logger');
unleashLogger.setLoggerProvider(consoleLoggerProvider);
// then require unleash-server and continue as normal
const unleash = require('unleash-server');
```

View File

@ -6,6 +6,7 @@ title: Google Auth Hook
This part of the tutorial shows how to create a sign-in flow for users and integrate with Unleash server project. The implementation assumes that I am working in `localhost` with `4242` port.
This is a simple `index.js` server file.
```javascript
const unleash = require('unleash-server');
@ -15,7 +16,7 @@ if (process.env.DATABASE_URL_FILE) {
unleash.start(options).then(unleash => {
console.log(`Unleash started on http://localhost:${unleash.app.get('port')}`);
});;
});
```
### Creating a web application client ID
@ -31,6 +32,7 @@ unleash.start(options).then(unleash => {
5. Type the **Name**.
6. Under **Authorized redirect URIs** enter the following URLs, one at a time.
```
http://localhost:4242/api/auth/callback
```
@ -39,58 +41,67 @@ http://localhost:4242/api/auth/callback
8. Copy the **CLIENT ID** and **CLIENT SECRET** and save them for later use.
### Add dependencies
Add two dependencies [`passport`](https://www.npmjs.com/package/passport) and [`passport-google-oauth20`](https://www.npmjs.com/package/passport-google-oauth20) inside `index.js` file
Add two dependencies [`passport`](https://www.npmjs.com/package/passport) and [`passport-google-oauth20`](https://www.npmjs.com/package/passport-google-oauth20) inside `index.js` file
```js
const unleash = require('unleash-server');
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
```
### Configure the Google strategy for use by Passport.js
OAuth 2-based strategies require a `verify` function which receives the credential (`accessToken`) for accessing the Google API on the user's behalf, along with the user's profile. The function must invoke `cb` with a user object, which will be set at `req.user` in route handlers after authentication.
```js
const GOOGLE_CLIENT_ID = '...';
const GOOGLE_CLIENT_SECRET = '...';
const GOOGLE_CALLBACK_URL = 'http://localhost:4242/api/auth/callback';
passport.use(new GoogleStrategy(
{
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: GOOGLE_CALLBACK_URL
},
function(accessToken, refreshToken, profile, cb) {
// Extract the minimal profile information we need from the profile object
// and connect with Unleash to get name and email.
cb(null, new unleash.User({
name: profile.displayName,
email: profile.emails[0].value,
}));
}
));
passport.use(
new GoogleStrategy(
{
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: GOOGLE_CALLBACK_URL,
},
function(accessToken, refreshToken, profile, cb) {
// Extract the minimal profile information we need from the profile object
// and connect with Unleash to get name and email.
cb(
null,
new unleash.User({
name: profile.displayName,
email: profile.emails[0].value,
}),
);
},
),
);
```
Add `googleAdminAuth()` function and other options
```js
function googleAdminAuth(app) {}
let options = {
enableLegacyRoutes: false,
adminAuthentication: 'custom',
preRouterHook: googleAdminAuth
preRouterHook: googleAdminAuth,
};
unleash.start(options).then(unleash => {
console.log(`Unleash started on http://localhost:${unleash.app.get('port')}`);
});;
});
```
### In `googleAdminAuth` function
Configure `passport` package.
```js
function googleAdminAuth(app) {
app.use(passport.initialize());
@ -102,32 +113,39 @@ function googleAdminAuth(app) {
```
Implement a preRouter hook for `/api/admin/login`. It's neccesary for login with Google.
```js
function googleAdminAuth(app) {
// ...
app.get('/api/admin/login', passport.authenticate('google', { scope: ['profile', 'email'] }));
app.get(
'/api/admin/login',
passport.authenticate('google', { scope: ['profile', 'email'] }),
);
// ...
}
```
Implement a preRouter hook for `/api/auth/callback`. It's a callback when the login is executed.
```js
function googleAdminAuth(app) {
// ...
app.get('/api/auth/callback',
app.get(
'/api/auth/callback',
passport.authenticate('google', {
failureRedirect: '/api/admin/error-login',
}),
(req, res) => {
// Successful authentication, redirect to your app.
res.redirect('/');
}
},
);
// ...
}
```
Implement a preRouter hook for `/api/admin`.
```js
function googleAdminAuth(app) {
// ...
@ -143,8 +161,9 @@ function googleAdminAuth(app) {
path: '/api/admin/login',
type: 'custom',
message: `You have to identify yourself in order to use Unleash. Click the button and follow the instructions.`,
})
).end();
}),
)
.end();
}
});
// ...
@ -152,7 +171,9 @@ function googleAdminAuth(app) {
```
### The complete code
The `index.js` server file.
```js
'use strict';
@ -164,19 +185,24 @@ const GOOGLE_CLIENT_ID = '...';
const GOOGLE_CLIENT_SECRET = '...';
const GOOGLE_CALLBACK_URL = 'http://localhost:4242/api/auth/callback';
passport.use(new GoogleStrategy(
{
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: GOOGLE_CALLBACK_URL
},
function(accessToken, refreshToken, profile, cb) {
cb(null, new unleash.User({
name: profile.displayName,
email: profile.emails[0].value,
}));
}
));
passport.use(
new GoogleStrategy(
{
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: GOOGLE_CALLBACK_URL,
},
function(accessToken, refreshToken, profile, cb) {
cb(
null,
new unleash.User({
name: profile.displayName,
email: profile.emails[0].value,
}),
);
},
),
);
function googleAdminAuth(app) {
app.use(passport.initialize());
@ -184,14 +210,18 @@ function googleAdminAuth(app) {
passport.serializeUser((user, done) => done(null, user));
passport.deserializeUser((user, done) => done(null, user));
app.get('/api/admin/login', passport.authenticate('google', { scope: ['profile', 'email'] }));
app.get('/api/auth/callback',
app.get(
'/api/admin/login',
passport.authenticate('google', { scope: ['profile', 'email'] }),
);
app.get(
'/api/auth/callback',
passport.authenticate('google', {
failureRedirect: '/api/admin/error-login',
}),
(req, res) => {
res.redirect('/');
}
},
);
app.use('/api/admin/', (req, res, next) => {
@ -205,8 +235,9 @@ function googleAdminAuth(app) {
path: '/api/admin/login',
type: 'custom',
message: `You have to identify yourself in order to use Unleash. Click the button and follow the instructions.`,
})
).end();
}),
)
.end();
}
});
}
@ -214,7 +245,7 @@ function googleAdminAuth(app) {
let options = {
enableLegacyRoutes: false,
adminAuthentication: 'custom',
preRouterHook: googleAdminAuth
preRouterHook: googleAdminAuth,
};
if (process.env.DATABASE_URL_FILE) {
@ -223,5 +254,5 @@ if (process.env.DATABASE_URL_FILE) {
unleash.start(options).then(unleash => {
console.log(`Unleash started on http://localhost:${unleash.app.get('port')}`);
});;
});
```

View File

@ -3,29 +3,31 @@ id: migration_guide
title: Migration Guide
---
Generally the intention is that `unleash-server` should always provide support for clients one lower major version. This should make possible to upgrade `unleash` gradually.
Generally the intention is that `unleash-server` should always provide support for clients one lower major version. This should make possible to upgrade `unleash` gradually.
## Upgrading from v2.x to v3.x
The notable change introduced in Unleash v3.x is a strict separation of api paths for client requests and admin requests. This makes it easier to implement different authentication mechanisms for the admin UI and all unleash-clients. You can read more about [securing unleash](https://github.com/Unleash/unleash/blob/master/docs/securing-unleash.md).
The recommended approach is to first upgrade the `unleash-server` to v3 (which still supports v2 clients). After this is done you should upgrade all your clients to v3.
The notable change introduced in Unleash v3.x is a strict separation of api paths for client requests and admin requests. This makes it easier to implement different authentication mechanisms for the admin UI and all unleash-clients. You can read more about [securing unleash](https://github.com/Unleash/unleash/blob/master/docs/securing-unleash.md).
The recommended approach is to first upgrade the `unleash-server` to v3 (which still supports v2 clients). After this is done you should upgrade all your clients to v3.
After upgrading all your clients you should consider turning off legacy routes, used by v2 clients. Read more about this option in in the [gettings started guide](https://github.com/Unleash/unleash/blob/master/docs/getting-started.md#2-or-programmatically).
## Upgrading from v1.0 to v2.0
### Caveat 1: Not used db-migrate to migrate the unleash database?
In FINN we used, for internal reasons, liquebase to migrate our database.
Because unleash from version 2.0 migrates the database internally, with db-migrate,
you need to make sure that all previous migrations for version 1 exists, so unleash
does not try to create tables that already exists.
Because unleash from version 2.0 migrates the database internally, with db-migrate, you need to make sure that all previous migrations for version 1 exists, so unleash does not try to create tables that already exists.
#### How to check?
If you don't have a "migrations" table with _7 unique migrations_ you are affected by this.
If you don't have a "migrations" table with _7 unique migrations_ you are affected by this.
#### How to fix?
Before starting unleash version 2 you have to run the SQL located under `scripts/fix-migrations-version-1.sql`
### Caveat 2: databaseUrl (not database*Uri*)
Using unleash as a lib and injecting your own config? Then you should know that we changed the databaseUri config param name to **databaseUrl**. This to align it with the environment variable (DATABASE_URL), avoiding multiple names for same config param.
Using unleash as a lib and injecting your own config? Then you should know that we changed the databaseUri config param name to **databaseUrl**. This to align it with the environment variable (DATABASE_URL), avoiding multiple names for same config param.

View File

@ -3,48 +3,53 @@ id: securing_unleash
title: Securing Unleash
---
The Unleash API is split in two different paths: `/api/client` and `/api/admin`.
This makes it easy to have different authentication strategy for the admin interface and the client-api used by the applications integrating with Unleash.
The Unleash API is split in two different paths: `/api/client` and `/api/admin`. This makes it easy to have different authentication strategy for the admin interface and the client-api used by the applications integrating with Unleash.
## General settings
Unleash uses an encrypted cookie to maintain a user session. This allows users to be logged in across instances of Unleash. To protect this cookie you should specify the `secret` option when starting unleash.-
Unleash uses an encrypted cookie to maintain a user session. This allows users to be logged in across instances of Unleash. To protect this cookie you should specify the `secret` option when starting unleash.-
## Securing the Admin API
In order to secure the Admin API you have to tell Unleash that you are using a custom admin authentication and implement your authentication logic as a preHook. You should also set the secret option to a protected secret in your system.
In order to secure the Admin API you have to tell Unleash that you are using a custom admin authentication and implement your authentication logic as a preHook. You should also set the secret option to a protected secret in your system.
```javascript
const unleash = require('unleash-server');
const myCustomAdminAuth = require('./auth-hook');
unleash.start({
databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
secret: 'super-duper-secret',
adminAuthentication: 'custom',
preRouterHook: myCustomAdminAuth
}).then(unleash => {
console.log(`Unleash started on http://localhost:${unleash.app.get('port')}`);
});
unleash
.start({
databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
secret: 'super-duper-secret',
adminAuthentication: 'custom',
preRouterHook: myCustomAdminAuth,
})
.then(unleash => {
console.log(
`Unleash started on http://localhost:${unleash.app.get('port')}`,
);
});
```
Additionally, you can trigger the admin interface to prompt the user to sign in by configuring your middleware to return a `401` status on
protected routes. The response body must contain a `message` and a `path` used to redirect the user to the proper login route.
Additionally, you can trigger the admin interface to prompt the user to sign in by configuring your middleware to return a `401` status on protected routes. The response body must contain a `message` and a `path` used to redirect the user to the proper login route.
```json
{
"message": "You must be logged in to use Unleash",
"path": "/custom/login"
"message": "You must be logged in to use Unleash",
"path": "/custom/login"
}
```
Examples on custom authentication hooks:
- [google-auth-hook.js](https://github.com/Unleash/unleash/blob/master/examples/google-auth-hook.js)
- [basic-auth-hook.js](https://github.com/Unleash/unleash/blob/master/examples/basic-auth-hook.js)
We also have a version of Unleash deployed on Heroku which uses Google OAuth 2.0:
https://secure-unleash.herokuapp.com
We also have a version of Unleash deployed on Heroku which uses Google OAuth 2.0: https://secure-unleash.herokuapp.com
## Securing the Client API
A common way to support client access is to use pre shared secrets. This can be solved by having clients send a shared key in a http header with every client request to the Unleash API. All official Unleash clients should support this.
A common way to support client access is to use pre shared secrets. This can be solved by having clients send a shared key in a http header with every client request to the Unleash API. All official Unleash clients should support this.
In the [Java client](https://github.com/Unleash/unleash-client-java#custom-http-headers) this looks like:
@ -63,24 +68,27 @@ On the unleash server side you need to implement a preRouter hook which verifies
const unleash = require('unleash-server');
const sharedSecret = '12312Random';
unleash.start({
databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
enableLegacyRoutes: false,
preRouterHook: app => {
unleash
.start({
databaseUrl: 'postgres://unleash_user:passord@localhost:5432/unleash',
enableLegacyRoutes: false,
preRouterHook: app => {
app.use('/api/client', (req, res, next) => {
if (req.header('authorization') !== sharedSecret) {
res.sendStatus(401);
res.sendStatus(401);
} else {
next();
next();
}
});
}
}).then(unleash => {
console.log(`Unleash started on http://localhost:${unleash.app.get('port')}`);
});
},
})
.then(unleash => {
console.log(
`Unleash started on http://localhost:${unleash.app.get('port')}`,
);
});
```
[client-auth-unleash.js](https://github.com/Unleash/unleash/blob/master/examples/client-auth-unleash.js)
PS! Remember to disable legacy route by setting the `enableLegacyRoutes` option to false. This will require all your clients to be on v3.x.
PS! Remember to disable legacy route by setting the `enableLegacyRoutes` option to false. This will require all your clients to be on v3.x.

View File

@ -3,10 +3,7 @@ id: unleash_context
title: Unleash Context
---
In order to standardise a few activation strategies we also needed to
standardise a unleash context, which contains some fields that varies
per requests, needed to implement the activation strategies.
In order to standardise a few activation strategies we also needed to standardise a unleash context, which contains some fields that varies per requests, needed to implement the activation strategies.
The unleash context is defined by these fields:
@ -15,12 +12,8 @@ The unleash context is defined by these fields:
- remoteAddress: String,
- properties: Map<String, String>
All fields are optional, but if they are not set you will not be able to use
certain activation strategies.
All fields are optional, but if they are not set you will not be able to use certain activation strategies.
E.g. the userWithId-strategy obviously depends on the userId field.
E.g. the userWithId-strategy obviously depends on the userId field.
The properties field is more generic and can be used to provide more abritary
data to the strategies. A common usage is to add more metadata, e.g. that the
current user is a beta user, and thus the betaUser-strategy will use this info
in its implementation.
The properties field is more generic and can be used to provide more abritary data to the strategies. A common usage is to add more metadata, e.g. that the current user is a beta user, and thus the betaUser-strategy will use this info in its implementation.

View File

@ -7,71 +7,85 @@
{
"name": "userWithId",
"description": "Active for users with a userId defined in the userIds-list",
"parameters": [{
"name": "userIds",
"type": "list",
"description": "",
"required": false
}]
"parameters": [
{
"name": "userIds",
"type": "list",
"description": "",
"required": false
}
]
},
{
"name": "applicationHostname",
"description": "Active for client instances with a hostName in the hostNames-list.",
"parameters": [{
"name": "hostNames",
"type": "list",
"description": "List of hostnames to enable the feature toggle for.",
"required": false
}]
"parameters": [
{
"name": "hostNames",
"type": "list",
"description": "List of hostnames to enable the feature toggle for.",
"required": false
}
]
},
{
"name": "gradualRolloutRandom",
"description": "Randomly activate the feature toggle. No stickiness.",
"parameters": [{
"name": "percentage",
"type": "percentage",
"description": "",
"required": false
}]
"parameters": [
{
"name": "percentage",
"type": "percentage",
"description": "",
"required": false
}
]
},
{
"name": "gradualRolloutSessionId",
"description": "Gradually activate feature toggle. Stickiness based on session id.",
"parameters": [{
"name": "percentage",
"type": "percentage",
"description": "",
"required": false
},{
"name": "groupId",
"type": "string",
"description": "Used to define a activation groups, which allows you to correlate across feature toggles.",
"required": true
}]
"parameters": [
{
"name": "percentage",
"type": "percentage",
"description": "",
"required": false
},
{
"name": "groupId",
"type": "string",
"description": "Used to define a activation groups, which allows you to correlate across feature toggles.",
"required": true
}
]
},
{
"name": "gradualRolloutUserId",
"description": "Gradually activate feature toggle for logged in users. Stickiness based on user id.",
"parameters": [{
"name": "percentage",
"type": "percentage",
"description": "",
"required": false
},{
"name": "groupId",
"type": "string",
"description": "Used to define a activation groups, which allows you to correlate across feature toggles.",
"required": true
}]
"parameters": [
{
"name": "percentage",
"type": "percentage",
"description": "",
"required": false
},
{
"name": "groupId",
"type": "string",
"description": "Used to define a activation groups, which allows you to correlate across feature toggles.",
"required": true
}
]
},
{
"name": "remoteAddress",
"description": "Active for remote addresses defined in the IPs list.",
"parameters": [{
"name": "IPs",
"type": "list",
"description": "List of IPs to enable the feature toggle for.",
"required": true
}]
"parameters": [
{
"name": "IPs",
"type": "list",
"description": "List of IPs to enable the feature toggle for.",
"required": true
}
]
}
]

View File

@ -1,113 +1,125 @@
{
"strategies": [
"strategies": [
{
"name": "default",
"description": "Default on or off Strategy.",
"parameters": []
},
{
"name": "usersWithEmail",
"description": "Active for users defined in the comma-separated emails-parameter.",
"parameters": [
{
"name": "default",
"description": "Default on or off Strategy.",
"parameters": []
},
{
"name": "usersWithEmail",
"description": "Active for users defined in the comma-separated emails-parameter.",
"parameters": [{
"name": "emails",
"type": "string"
}]
}
],
"applications": [
{
"appName": "demo-app-1",
"strategies": ["default"]
},
{
"appName": "demo-app-2",
"strategies": ["default",
"extra"
],
"description": "hello"
"name": "emails",
"type": "string"
}
],
"clientInstances": [
]
}
],
"applications": [
{
"appName": "demo-app-1",
"strategies": ["default"]
},
{
"appName": "demo-app-2",
"strategies": ["default", "extra"],
"description": "hello"
}
],
"clientInstances": [
{
"appName": "demo-app-1",
"instanceId": "test-1",
"strategies": ["default"],
"started": 1516026938494,
"interval": 10
},
{
"appName": "demo-seed-2",
"instanceId": "test-2",
"strategies": ["default"],
"started": 1516026938494,
"interval": 10
}
],
"features": [
{
"name": "featureX",
"description": "the #1 feature",
"enabled": true,
"strategies": [
{
"appName": "demo-app-1",
"instanceId": "test-1",
"strategies": ["default"],
"started": 1516026938494,
"interval": 10
},
{
"appName": "demo-seed-2",
"instanceId": "test-2",
"strategies": ["default"],
"started": 1516026938494,
"interval": 10
"name": "default",
"parameters": {}
}
],
"features": [
]
},
{
"name": "featureY",
"description": "soon to be the #1 feature",
"enabled": false,
"strategies": [
{
"name": "featureX",
"description": "the #1 feature",
"enabled": true,
"strategies": [{
"name": "default",
"parameters": {}
}]
},
{
"name": "featureY",
"description": "soon to be the #1 feature",
"enabled": false,
"strategies": [{
"name": "baz",
"parameters": {
"foo": "bar"
}
}]
},
{
"name": "featureZ",
"description": "terrible feature",
"enabled": true,
"strategies": [{
"name": "baz",
"parameters": {
"foo": "rab"
}
}]
},
{
"name": "featureArchivedX",
"description": "the #1 feature",
"enabled": true,
"archived": true,
"strategies": [{
"name": "default",
"parameters": {}
}]
},
{
"name": "featureArchivedY",
"description": "soon to be the #1 feature",
"enabled": false,
"archived": true,
"strategies": [{
"name": "baz",
"parameters": {
"foo": "bar"
}
}]
},
{
"name": "featureArchivedZ",
"description": "terrible feature",
"enabled": true,
"archived": true,
"strategies": [{
"name": "baz",
"parameters": {
"foo": "rab"
}
}]
"name": "baz",
"parameters": {
"foo": "bar"
}
}
]
}
]
},
{
"name": "featureZ",
"description": "terrible feature",
"enabled": true,
"strategies": [
{
"name": "baz",
"parameters": {
"foo": "rab"
}
}
]
},
{
"name": "featureArchivedX",
"description": "the #1 feature",
"enabled": true,
"archived": true,
"strategies": [
{
"name": "default",
"parameters": {}
}
]
},
{
"name": "featureArchivedY",
"description": "soon to be the #1 feature",
"enabled": false,
"archived": true,
"strategies": [
{
"name": "baz",
"parameters": {
"foo": "bar"
}
}
]
},
{
"name": "featureArchivedZ",
"description": "terrible feature",
"enabled": true,
"archived": true,
"strategies": [
{
"name": "baz",
"parameters": {
"foo": "rab"
}
}
]
}
]
}

View File

@ -1,18 +1,18 @@
{
"appName": "appName",
"instanceId": "instanceId",
"bucket": {
"start": "2016-11-03T07:16:43.572Z",
"stop": "2016-11-03T07:16:53.572Z",
"toggles": {
"toggle-name-1": {
"yes": 123,
"no": 321
},
"toggle-name-2": {
"yes": 111,
"no": 0
}
}
"appName": "appName",
"instanceId": "instanceId",
"bucket": {
"start": "2016-11-03T07:16:43.572Z",
"stop": "2016-11-03T07:16:53.572Z",
"toggles": {
"toggle-name-1": {
"yes": 123,
"no": 321
},
"toggle-name-2": {
"yes": 111,
"no": 0
}
}
}
}

View File

@ -1,8 +1,8 @@
{
"appName": "appName",
"instanceId": "instanceId",
"sdkVersion": "test:123",
"strategies": ["default", "some-strategy-1"],
"started": "2016-11-03T07:16:43.572Z",
"interval": 10000
"appName": "appName",
"instanceId": "instanceId",
"sdkVersion": "test:123",
"strategies": ["default", "some-strategy-1"],
"started": "2016-11-03T07:16:43.572Z",
"interval": 10000
}

View File

@ -4,11 +4,11 @@ It's hosted on https://unleash.github.io/
# What's In This Document
* [Get Started in 5 Minutes](#get-started-in-5-minutes)
* [Directory Structure](#directory-structure)
* [Editing Content](#editing-content)
* [Adding Content](#adding-content)
* [Full Documentation](#full-documentation)
- [Get Started in 5 Minutes](#get-started-in-5-minutes)
- [Directory Structure](#directory-structure)
- [Editing Content](#editing-content)
- [Adding Content](#adding-content)
- [Full Documentation](#full-documentation)
# Get Started in 5 Minutes
@ -18,6 +18,7 @@ It's hosted on https://unleash.github.io/
# Install dependencies
$ npm install
```
2. Run your dev server:
```sh
@ -103,6 +104,7 @@ For more information about adding new docs, click [here](https://docusaurus.io/d
1. Add links to docs, custom pages or external links by editing the headerLinks field of `website/siteConfig.js`:
`website/siteConfig.js`
```javascript
{
headerLinks: [
@ -127,6 +129,7 @@ For more information about the navigation bar, click [here](https://docusaurus.i
1. If you want your page to show up in your navigation header, you will need to update `website/siteConfig.js` to add to the `headerLinks` element:
`website/siteConfig.js`
```javascript
{
headerLinks: [

View File

@ -1,13 +1,37 @@
{
"documentation": {
<<<<<<< HEAD
"User documentation": ["getting_started", "client_sdk", "securing_unleash", "unleash_context", "activation_strategy", "client_specification", "migration_guide"],
"Developer Guide": ["developer_guide", "database_schema", "database_backup"],
=======
"Getting Started": [
"getting_started",
"securing_unleash",
"unleash_context",
"activation_strategy",
"client_specification",
"migration_guide"
],
"Developer Guide": [
"developer_guide",
"database_schema",
"database_backup"
],
>>>>>>> chore: Fix formatting all the things
"Guides": ["guides/google_auth"]
},
"api": {
"Client": ["api/client/features", "api/client/register", "api/client/metrics"],
"Admin": ["api/admin/features", "api/admin/strategies", "api/admin/metrics", "api/admin/events" ],
"Internal": ["api/internal" ]
"Client": [
"api/client/features",
"api/client/register",
"api/client/metrics"
],
"Admin": [
"api/admin/features",
"api/admin/strategies",
"api/admin/metrics",
"api/admin/events"
],
"Internal": ["api/internal"]
}
}

View File

@ -16,9 +16,9 @@
}
h2.projectTitle {
color: black;
color: black;
}
.blockImage img {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
}