diff --git a/app/app.js b/app/app.js index 568b9b57a..8e14e634c 100644 --- a/app/app.js +++ b/app/app.js @@ -26,7 +26,7 @@ const App = Application.extend({ dependencies: { services: [ 'access', - 'auth-store', + 'authn-store', 'catalog', 'endpoint', 'github', diff --git a/app/application/controller.js b/app/application/controller.js index f33062117..e6f5fed4b 100644 --- a/app/application/controller.js +++ b/app/application/controller.js @@ -1,6 +1,7 @@ import { oneWay } from '@ember/object/computed'; import { inject as service } from '@ember/service'; import Controller from '@ember/controller'; +import { run } from '@ember/runloop'; export default Controller.extend({ settings: service(), @@ -28,6 +29,14 @@ export default Controller.extend({ }, }, + init() { + this._super(...arguments); + + if ( this.get('app.environment') === 'development' ) { + run.backburner.DEBUG = true; + } + }, + // currentRouteName is set by Ember.Router // but getting the application controller to get it is inconvenient sometimes currentRouteNameChanged: function() { diff --git a/app/application/route.js b/app/application/route.js index f751e18ab..8576ba167 100644 --- a/app/application/route.js +++ b/app/application/route.js @@ -77,6 +77,7 @@ export default Route.extend({ this.transitionTo('failWhale'); console.log('Application Error', (err ? err.stack : undefined)); + debugger; }, goToPrevious(def) { diff --git a/app/authenticated/route.js b/app/authenticated/route.js index 76f044a3a..dffb7fd4b 100644 --- a/app/authenticated/route.js +++ b/app/authenticated/route.js @@ -7,13 +7,13 @@ import Route from '@ember/routing/route'; import Subscribe from 'ui/mixins/subscribe'; import { inject as service } from '@ember/service'; import { later, scheduleOnce, cancel } from '@ember/runloop'; -import { reject, Promise as EmberPromise, resolve } from 'rsvp'; -import { xhrConcur } from 'ui/utils/platform'; +import { reject, resolve, all as PromiseAll } from 'rsvp'; const CHECK_AUTH_TIMER = 60*10*1000; export default Route.extend(Subscribe, PromiseToCb, { access: service(), + authnStore: service('authn-store'), clusterStore: service('cluster-store'), cookies: service(), language: service('user-language'), @@ -58,45 +58,25 @@ export default Route.extend(Subscribe, PromiseToCb, { this.get('session').set(C.SESSION.BACK_TO, undefined); - let promise = new EmberPromise((resolve, reject) => { - let tasks = { - userSchemas: this.toCb('loadUserSchemas'), - clusters: this.toCb('loadClusters'), - projects: this.toCb('loadProjects'), - preferences: this.toCb('loadPreferences'), - settings: this.toCb('loadPublicSettings'), - project: ['clusters','projects', 'preferences', - this.toCb('selectProject',transition)], - projectSchemas: ['project', this.toCb('loadProjectSchemas')], - instances: ['projectSchemas', this.cbFind('instance')], - services: ['projectSchemas', this.cbFind('service')], - hosts: ['projectSchemas', this.cbFind('host')], - stacks: ['projectSchemas', this.cbFind('stack')], - mounts: ['projectSchemas', this.cbFind('mount', 'store', {filter: {state_ne: 'inactive'}})], - storagePools: ['projectSchemas', this.cbFind('storagepool')], - volumes: ['projectSchemas', this.cbFind('volume')], - volumeTemplates: ['projectSchemas', this.cbFind('volumetemplate')], - certificate: ['projectSchemas', this.cbFind('certificate')], - secret: ['projectSchemas', this.toCb('loadSecrets')], - identities: ['userSchemas', this.cbFind('identity', 'userStore')], - }; - - async.auto(tasks, xhrConcur, function(err, res) { - if ( err ) { - reject(err); - } else { - resolve(res); - } - }); - }, 'Load all the things'); - - return promise.then((hash) => { - return EmberObject.create(hash); + return PromiseAll([ + this.loadSchemas('clusterStore'), +// this.loadSchemas('authnStore'), + this.loadClusters(), + this.loadProjects() + //this.loadPreferences(), + //this.loadPublicSettings() + ]).then(() => { + return this.selectProject(transition); + }).then(() => { + return this.loadSchemas('store'); + }).then(() => { + return PromiseAll([ + this.preload('workload'), + this.preload('nodes'), + this.preload('pods'), + ]); }).catch((err) => { - return this.loadingError(err, transition, EmberObject.create({ - projects: [], - project: null, - })); + return this.loadingError(err, transition); }); }, @@ -139,35 +119,23 @@ export default Route.extend(Subscribe, PromiseToCb, { this.get('storeReset').reset(); }, - loadingError(err, transition, ret) { + loadingError(err, transition) { let isAuthEnabled = this.get('access.enabled'); - let isAuthFail = [401,403].indexOf(err.status) >= 0; + let isAuthFail = err && err.status && [401,403].indexOf(err.status) >= 0; var msg = Errors.stringify(err); console.log('Loading Error:', msg, err); if ( err && (isAuthEnabled || isAuthFail) ) { this.set('access.enabled', true); this.send('logout', transition, isAuthFail, (isAuthFail ? undefined : msg)); - return; + } else { + this.replaceWith('authenticated.clusters'); } - this.replaceWith('authenticated.clusters'); - return ret; }, - cbFind(type, store='store', opt=null) { - return (results, cb) => { - if ( typeof results === 'function' ) { - cb = results; - results = null; - } - - return this.get(store).find(type,null,opt).then(function(res) { - cb(null, res); - }).catch(function(err) { - cb(err, null); - }); - }; + preload(type, store='store', opt=null) { + return this.get(store).find(type,null,opt); }, loadPreferences() { @@ -189,22 +157,14 @@ export default Route.extend(Subscribe, PromiseToCb, { }); }, - loadProjectSchemas() { - var store = this.get('store'); + loadSchemas(storeName) { + var store = this.get(storeName); store.resetType('schema'); return store.rawRequest({url:'schema', dataType: 'json'}).then((xhr) => { store._bulkAdd('schema', xhr.body.data); }); }, - loadUserSchemas() { - // @TODO Inline me into releases - let userStore = this.get('userStore'); - return userStore.rawRequest({url:'schema', dataType: 'json'}).then((xhr) => { - userStore._bulkAdd('schema', xhr.body.data); - }); - }, - loadClusters() { let svc = this.get('scope'); return svc.getAllClusters().then((all) => { @@ -281,7 +241,7 @@ export default Route.extend(Subscribe, PromiseToCb, { error(err,transition) { // Unauthorized error, send back to login screen - if ( err.status === 401 ) + if ( err && err.status === 401 ) { this.send('logout',transition,true); return false; diff --git a/app/initializers/auth-store.js b/app/initializers/authn-store.js similarity index 51% rename from app/initializers/auth-store.js rename to app/initializers/authn-store.js index 54ac71ab1..8c1c6485d 100644 --- a/app/initializers/auth-store.js +++ b/app/initializers/authn-store.js @@ -1,6 +1,6 @@ import initializer from 'ember-api-store/initializers/store'; export default { - name: 'auth-store', - initialize: initializer('auth-store','authStore') + name: 'authn-store', + initialize: initializer('authn-store','authnStore') }; diff --git a/app/instance-initializers/auth-store.js b/app/instance-initializers/authn-store.js similarity index 52% rename from app/instance-initializers/auth-store.js rename to app/instance-initializers/authn-store.js index 3e73e75ab..c4491c0eb 100644 --- a/app/instance-initializers/auth-store.js +++ b/app/instance-initializers/authn-store.js @@ -2,17 +2,13 @@ import StoreTweaks from 'ui/mixins/store-tweaks'; export function initialize(instance) { var application = instance.lookup('application:main'); - var store = instance.lookup('service:auth-store'); + var store = instance.lookup('service:authn-store'); store.reopen(StoreTweaks); - store.reopen({ - removeAfterDelete: false, - baseUrl: application.authEndpoint, - skipTypeifyKeys: ['labels'], - }); + store.baseUrl = application.authenticationEndpoint; } export default { - name: 'auth-store', + name: 'authn-store', initialize: initialize }; diff --git a/app/instance-initializers/cluster-store.js b/app/instance-initializers/cluster-store.js index 26ebdfd36..a076873f9 100644 --- a/app/instance-initializers/cluster-store.js +++ b/app/instance-initializers/cluster-store.js @@ -6,7 +6,7 @@ export function initialize(instance) { var cookies = instance.lookup('service:cookies'); store.reopen(StoreTweaks); - store.baseUrl = application.apiEndpoint; + store.baseUrl = application.clusterEndpoint; let timeout = cookies.get('timeout'); if ( timeout ) { diff --git a/config/environment.js b/config/environment.js index 2734f2106..7c92e522b 100644 --- a/config/environment.js +++ b/config/environment.js @@ -99,7 +99,10 @@ module.exports = function(environment) { environment: environment, apiServer: 'http://localhost:8080', legacyApiEndpoint: '/v2', - apiEndpoint: '/v3', + apiEndpoint: '/v1-workload', + clusterEndpoint: '/v1-cluster', + authenticationEndpoint: '/v1-authn', + authorizationEndpoint: '/v1-authz', // betaApiEndpoint: '/v3', catalogServer: '', catalogEndpoint: '/v1-catalog', diff --git a/lib/global-admin/addon/engine.js b/lib/global-admin/addon/engine.js index bfba76c51..9d918bc24 100644 --- a/lib/global-admin/addon/engine.js +++ b/lib/global-admin/addon/engine.js @@ -11,7 +11,7 @@ const Eng = Engine.extend({ dependencies: { services: [ 'access', - 'auth-store', + 'authn-store', 'catalog', 'endpoint', 'github', diff --git a/lib/global-admin/addon/routes/accounts/index.js b/lib/global-admin/addon/routes/accounts/index.js index 897d70889..62efe6b30 100644 --- a/lib/global-admin/addon/routes/accounts/index.js +++ b/lib/global-admin/addon/routes/accounts/index.js @@ -4,6 +4,6 @@ import { inject as service } from '@ember/service' export default Route.extend({ userStore: service('user-store'), model: function() { - return this.get('userStore').find('account', null, {filter: {'kind_ne': ['service','agent']}, forceReload: true}); +// @TODO need schemas... return this.get('userStore').find('account', null, {filter: {'kind_ne': ['service','agent']}, forceReload: true}); }, }); diff --git a/lib/global-admin/addon/routes/application.js b/lib/global-admin/addon/routes/application.js index 06806c454..83a874716 100644 --- a/lib/global-admin/addon/routes/application.js +++ b/lib/global-admin/addon/routes/application.js @@ -14,8 +14,9 @@ export default Route.extend({ this.get('scope').setPageScope('cluster'); } }, + redirect() { - this.transitionTo('settings.auth'); + this.transitionTo('accounts'); }, beforeModel() { @@ -29,6 +30,12 @@ export default Route.extend({ model() { let settings = this.get('settings'); + return EmberObject.create({ + host: '', + catalog: '', + telemetry: 'out', + }); + return this.get('userStore').find('setting').then(() => { return EmberObject.create({ host: settings.get(C.SETTING.API_HOST), diff --git a/lib/global-admin/addon/routes/settings/auth/github.js b/lib/global-admin/addon/routes/settings/auth/github.js index 086f8824c..268db7c8f 100644 --- a/lib/global-admin/addon/routes/settings/auth/github.js +++ b/lib/global-admin/addon/routes/settings/auth/github.js @@ -2,9 +2,9 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - authStore: service('auth-store'), + authnStore: service('authn-store'), model: function() { - return this.get('authStore').find('config', null, {forceReload: true}).then(function(collection) { + return this.get('authnStore').find('config', null, {forceReload: true}).then(function(collection) { return collection; }); }, diff --git a/lib/global-admin/addon/routes/settings/auth/index.js b/lib/global-admin/addon/routes/settings/auth/index.js index 04c4eb9c4..410399cd3 100644 --- a/lib/global-admin/addon/routes/settings/auth/index.js +++ b/lib/global-admin/addon/routes/settings/auth/index.js @@ -3,12 +3,6 @@ import { inject as service } from '@ember/service'; export default Route.extend({ access: service(), - authStore: service('auth-store'), - beforeModel: function() { - return this.get('authStore').rawRequest({url: '/v1-auth/schemas', dataType: 'json'}).then((resp) => { - return this.get('authStore')._bulkAdd('schema', resp.body.data); - }); - }, model: function() { var route = (this.get('access.provider')||'').toLowerCase().replace(/config$/i,''); diff --git a/lib/global-admin/addon/routes/settings/auth/shibboleth.js b/lib/global-admin/addon/routes/settings/auth/shibboleth.js index bf3076cfd..babfd38a7 100644 --- a/lib/global-admin/addon/routes/settings/auth/shibboleth.js +++ b/lib/global-admin/addon/routes/settings/auth/shibboleth.js @@ -2,9 +2,9 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default Route.extend({ - authStore: service('auth-store'), + authnStore: service('authn-store'), model: function() { - return this.get('authStore').find('config', null, {forceReload: true}).then(function(collection) { + return this.get('authnStore').find('config', null, {forceReload: true}).then(function(collection) { return collection; }); }, diff --git a/lib/global-admin/config/environment.js b/lib/global-admin/config/environment.js index 9f29a510c..1bef8157d 100644 --- a/lib/global-admin/config/environment.js +++ b/lib/global-admin/config/environment.js @@ -8,37 +8,6 @@ module.exports = function(environment) { modulePrefix: 'global-admin', environment: environment, APP: { - // Here you can pass flags/options to your application instance - // when it is created - appName: 'Rancher', - mode: mode, - environment: environment, - apiServer: 'http://localhost:8080', - legacyApiEndpoint: '/v2', - apiEndpoint: '/v3', - catalogServer: '', - catalogEndpoint: '/v1-catalog', - authServer: '', - authEndpoint: '/v1-auth', - telemetryEndpoint: '/v1-telemetry', - webhookEndpoint: '/v1-webhooks', - clusterToken: '%CLUSTERID%', - projectToken: '%PROJECTID%', - magicEndpoint: '/r', - kubernetesBase: '/k8s', - kubectlEndpoint: '/r/projects/%PROJECTID%/kubectld:8091/v1-kubectl', - kubernetesDashboard: '/k8s/clusters/%CLUSTERID%/api/v1/namespaces/kube-system/services/kubernetes-dashboard/proxy/', - projectEndpoint: '/v3/projects/%PROJECTID%', - proxyEndpoint: '/v3/proxy', - wsEndpoint: '/v3/projects/%PROJECTID%/subscribe' + - '?eventNames=resource.change' + - '&resourceType_ne=auditLog' + - '&resourceType_ne=serviceLog' + - '&resourceType_ne=deploymentUnit', - baseAssets: '/', - stripe: { - publishableKey: 'pk_test_g925RcuVORh2KgHWfFbE80by' - }, }, }; diff --git a/lib/shared/addon/access/service.js b/lib/shared/addon/access/service.js index 44b8fae7c..962aaf6b3 100644 --- a/lib/shared/addon/access/service.js +++ b/lib/shared/addon/access/service.js @@ -17,7 +17,7 @@ export default Service.extend({ // These are set by authenticated/route // Is access control enabled - enabled: null, + enabled: false, // @TODO have auth again someday... null, // What kind of access control provider: null, diff --git a/lib/shared/addon/components/container/form-networking/component.js b/lib/shared/addon/components/container/form-networking/component.js index b62a80968..0924fdabf 100644 --- a/lib/shared/addon/components/container/form-networking/component.js +++ b/lib/shared/addon/components/container/form-networking/component.js @@ -1,5 +1,4 @@ import { equal } from '@ember/object/computed'; -import { computed } from '@ember/object'; import { inject as service } from '@ember/service'; import Component from '@ember/component'; import ContainerChoices from 'ui/mixins/container-choices'; diff --git a/lib/shared/addon/scope/service.js b/lib/shared/addon/scope/service.js index ec0001aa8..91bd8e841 100644 --- a/lib/shared/addon/scope/service.js +++ b/lib/shared/addon/scope/service.js @@ -3,7 +3,6 @@ import { resolve, Promise as EmberPromise } from 'rsvp'; -import { alias } from '@ember/object/computed'; import Service, { inject as service } from '@ember/service'; import C from 'shared/utils/constants'; import { computed } from '@ember/object'; @@ -26,6 +25,12 @@ export default Service.extend({ // currentCluster: alias('current.cluster'), + init() { + this._super(...arguments); + this.set('all', []); + this.set('allClusters', []); + }, + setPageScope: function(scope) { return this.set('currentPageScope', scope); }, @@ -48,10 +53,11 @@ export default Service.extend({ } // TODO - this will change to use the clusters store when api is ready - return this.get('userStore').find('project', null, opt).then(() => { - return this.get('userStore').all('project'); + return this.get('store').find('project', null, opt).then(() => { + return this.get('store').all('project'); }); }, + getAllClusters: function() { var opt = { url: 'clusters', // This is called in authenticated/route before schemas are loaded @@ -82,10 +88,10 @@ export default Service.extend({ }); }, - selectDefaultCluster: function(desired) { + selectDefaultCluster: function() { var self = this; var cookies = this.get('cookies'); - this.controller + return this._activeClusterFromId(cookies.get(C.COOKIE.CLUSTER)).then(selectCluster) .catch(() => { @@ -102,24 +108,19 @@ export default Service.extend({ else if ( this.get('access.admin') ) { // Then if you're an admin the first active of any kind - return this.getAllClusters().then((all) => { - var firstActive = all.find((cluster) => { - return ACTIVEISH.includes(cluster.get('state')); - }); + var firstActive = this.get('allClusters').find((cluster) => { + return ACTIVEISH.includes(cluster.get('state')); + }); - if ( firstActive ) - { - return selectCluster(firstActive, true); - } - else - { - // go to cluster managment page - return clusterFail(); - } - }).catch(() => { + if ( firstActive ) + { + return selectCluster(firstActive, true); + } + else + { // go to cluster managment page return clusterFail(); - }); + } } else { @@ -145,7 +146,7 @@ export default Service.extend({ } else { - this.get('cookies').remove(C.COOKIE.CLUSTER); + cookies.remove(C.COOKIE.CLUSTER); return self.setCurrentCluster(null); } } @@ -183,22 +184,18 @@ export default Service.extend({ else if ( this.get('access.admin') ) { // Then if you're an admin the first active of any kind - return this.getAll().then((all) => { - var firstActive = all.find((project) => { - return ACTIVEISH.includes(project.get('state')); - }); - - if ( firstActive ) - { - return select(firstActive, true); - } - else - { - return this.selectDefaultCluster(null); - } - }).catch(() => { - return this.selectDefaultCluster(null); + var firstActive = this.get('all').find((project) => { + return ACTIVEISH.includes(project.get('state')); }); + + if ( firstActive ) + { + return select(firstActive, true); + } + else + { + return this.selectDefaultCluster(); + } } else { diff --git a/lib/shared/addon/settings/service.js b/lib/shared/addon/settings/service.js index cd2ebfbb6..0cfa48c17 100644 --- a/lib/shared/addon/settings/service.js +++ b/lib/shared/addon/settings/service.js @@ -1,5 +1,5 @@ import { alias } from '@ember/object/computed'; -import { Promise as EmberPromise } from 'rsvp'; +import { resolve, Promise as EmberPromise } from 'rsvp'; import { isArray } from '@ember/array'; import Evented from '@ember/object/evented'; import Service, { inject as service } from '@ember/service'; @@ -100,6 +100,8 @@ export default Service.extend(Evented, { }, load(names) { + return resolve(); + if ( !isArray(names) ) { names = [names]; } diff --git a/server/proxies/api.js b/server/proxies/api.js index 71e64f56f..bf312545a 100644 --- a/server/proxies/api.js +++ b/server/proxies/api.js @@ -26,16 +26,24 @@ module.exports = function(app, options) { let map = { 'API': config.apiEndpoint, + 'Cluster': config.clusterEndpoint, + 'AuthN': config.authenticationEndpoint, + 'AuthZ': config.authorizationEndpoint, + 'Catalog': config.catalogEndpoint, + // 'Beta API': config.betaApiEndpoint, - 'Legacy API': config.legacyApiEndpoint, +// 'Legacy API': config.legacyApiEndpoint, 'K8s': config.kubernetesBase, 'Magic': config.magicEndpoint, 'Telemetry': config.telemetryEndpoint, 'WebHook': config.webhookEndpoint, + + 'Meta': '/meta', + 'Swagger': '/swaggerapi', + 'Version': '/version', } - // Rancher API - console.log('Proxying API to', config.apiServer); + console.log('Proxying APIs to', config.apiServer); Object.keys(map).forEach(function(label) { let base = map[label]; app.use(base, function(req, res, next) { @@ -47,79 +55,6 @@ module.exports = function(app, options) { proxy.web(req, res); }); }); - - // New hotness - app.use('/meta', function(req, res, next) { - // include root path in proxied request - req.url = path.join('/meta', req.url); - req.headers['X-Forwarded-Proto'] = req.protocol; - - proxyLog('Meta', req); - proxy.web(req, res); - }); - - // Kubernetes needs this API - app.use('/swaggerapi', function(req, res, next) { - // include root path in proxied request - req.url = path.join('/swaggerapi', req.url); - req.headers['X-Forwarded-Proto'] = req.protocol; - - proxyLog('K8sSwag', req); - proxy.web(req, res); - }); - - app.use('/version', function(req, res, next) { - // include root path in proxied request - req.url = '/version'; - req.headers['X-Forwarded-Proto'] = req.protocol; - - proxyLog('K8sVers', req); - proxy.web(req, res); - }); - - // Catalog API - var catalogPath = config.catalogEndpoint; - // Default catalog to the regular API - var catalogServer = config.catalogServer || config.apiServer; - if ( catalogServer !== config.apiServer ) { - console.log('Proxying Catalog to', catalogServer); - } - app.use(catalogPath, function(req, res, next) { - req.headers['X-Forwarded-Proto'] = req.protocol; - var catalogProxy = HttpProxy.createProxyServer({ - xfwd: false, - target: catalogServer - }); - - catalogProxy.on('error', onProxyError); - - // include root path in proxied request - req.url = path.join(catalogPath, req.url); - - proxyLog('Catalog', req); - catalogProxy.web(req, res); - }); - - // Auth API - var authPath = config.authEndpoint; - var authServer = config.authServer || config.apiServer; - if ( authServer !== config.apiServer ) { - console.log('Proxying Auth to', authServer); - } - app.use(authPath, function(req, res, next) { - req.headers['X-Forwarded-Proto'] = req.protocol; - var catalogProxy = HttpProxy.createProxyServer({ - xfwd: false, - target: authServer - }); - - catalogProxy.on('error', onProxyError); - - req.url = path.join(authPath, req.url); - - proxyLog('Auth', req); - catalogProxy.web(req, res); - }); } function onProxyError(err, req, res) {