diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html index 01c16c5e21..97501ccc56 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html +++ b/src/frontend/packages/cloud-foundry/src/features/applications/application/application-tabs-base/tabs/build-tab/build-tab.component.html @@ -189,4 +189,32 @@ - \ No newline at end of file + + + + + + + Additional Application Info + + + {{ appSvc.app.entity.guid }} + {{ appSvc.app.entity.command || appSvc.app.entity.detected_start_command || '-' }} + {{ appSvc.app.entity.ports || '-' }} + + + + + + + Health Check Configuration + + + {{ appSvc.app.entity.health_check_type }} + {{ appSvc.app.entity.health_check_timeout | uptime }} + {{ appSvc.app.entity.health_check_http_endpoint }} + + + + + diff --git a/src/frontend/packages/cloud-foundry/src/features/applications/deploy-application/deploy-application-deployer.ts b/src/frontend/packages/cloud-foundry/src/features/applications/deploy-application/deploy-application-deployer.ts index e30e566377..cf15a1c671 100644 --- a/src/frontend/packages/cloud-foundry/src/features/applications/deploy-application/deploy-application-deployer.ts +++ b/src/frontend/packages/cloud-foundry/src/features/applications/deploy-application/deploy-application-deployer.ts @@ -1,5 +1,5 @@ import { Store } from '@ngrx/store'; -import { BehaviorSubject, Observable, of as observableOf, Subject, Subscription } from 'rxjs'; +import { BehaviorSubject, of as observableOf, Subject, Subscription } from 'rxjs'; import websocketConnect from 'rxjs-websockets'; import { catchError, combineLatest, filter, first, map, mergeMap, share, switchMap, tap } from 'rxjs/operators'; @@ -91,7 +91,7 @@ export class DeployApplicationDeployer { // Status of file transfers fileTransferStatus$ = new BehaviorSubject(undefined); - public messages: Observable; + public messages = new BehaviorSubject(''); // Are we deploying? deploying = false; @@ -165,13 +165,14 @@ export class DeployApplicationDeployer { this.applicationSource = appDetail.applicationSource; this.applicationOverrides = appDetail.applicationOverrides; const host = window.location.host; + const appId = this.isRedeploy ? `&app=${this.isRedeploy}` : ''; const streamUrl = ( `wss://${host}/pp/${this.proxyAPIVersion}/${this.cfGuid}/${this.orgGuid}/${this.spaceGuid}/deploy` + - `?org=${org.entity.name}&space=${space.entity.name}` + `?org=${org.entity.name}&space=${space.entity.name}${appId}` ); this.inputStream = new Subject(); - this.messages = websocketConnect(streamUrl) + const buffer = websocketConnect(streamUrl) .pipe( switchMap((get) => get(this.inputStream)), catchError(e => { @@ -189,7 +190,16 @@ export class DeployApplicationDeployer { map((log) => log.message), share(), ); - this.msgSub = this.messages.subscribe(); + + // Buffer messages until each newline character + let b = ''; + this.msgSub = buffer.subscribe(m => { + b = b + m; + if (b.endsWith('\n')) { + this.messages.next(b); + b = ''; + } + }); }) ).subscribe(); diff --git a/src/frontend/packages/core/src/shared/components/list/list-types/github-commits/github-commits-list-config-deploy.service.ts b/src/frontend/packages/core/src/shared/components/list/list-types/github-commits/github-commits-list-config-deploy.service.ts index 8dcb0bf35b..85fe999819 100644 --- a/src/frontend/packages/core/src/shared/components/list/list-types/github-commits/github-commits-list-config-deploy.service.ts +++ b/src/frontend/packages/core/src/shared/components/list/list-types/github-commits/github-commits-list-config-deploy.service.ts @@ -44,13 +44,15 @@ export class GithubCommitsListConfigServiceDeploy extends GithubCommitsListConfi this.initialised.next(true); // Auto-select first commit - wait for page to load, select first item if present - this.dataSource.page$.pipe( - first() - ).subscribe(rs => { - if (rs && rs.length > 0) { - this.dataSource.selectedRowToggle(rs[0], false); - } - }); + setTimeout(() => { + this.dataSource.page$.pipe( + first() + ).subscribe(rs => { + if (rs && rs.length > 0) { + this.dataSource.selectedRowToggle(rs[0], false); + } + }); + }, 0); }); } } diff --git a/src/jetstream/go.mod b/src/jetstream/go.mod index da7f830108..aecae07f82 100644 --- a/src/jetstream/go.mod +++ b/src/jetstream/go.mod @@ -5,14 +5,21 @@ go 1.12 require ( bitbucket.org/liamstask/goose v0.0.0-20150115234039-8488cc47d90c code.cloudfoundry.org/bytefmt v0.0.0-20180906201452-2aa6f33b730c // indirect - code.cloudfoundry.org/cli v6.43.0+incompatible + code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 // indirect + code.cloudfoundry.org/cli v6.49.0+incompatible + code.cloudfoundry.org/diego-ssh v0.0.0-20200312183824-517d22c5d890 // indirect code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f // indirect + code.cloudfoundry.org/inigo v0.0.0-20200318144131-597cd5dbfe8b // indirect + code.cloudfoundry.org/lager v2.0.0+incompatible // indirect + code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d // indirect github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect - github.com/SermoDigital/jose v0.9.1 + github.com/SermoDigital/jose v0.9.1 // indirect github.com/Sirupsen/logrus v0.0.0-00010101000000-000000000000 // indirect github.com/antonlindstrom/pgstore v0.0.0-20170604072116-a407030ba6d0 + github.com/apoydence/eachers v0.0.0-20181020210610-23942921fe77 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/bmatcuk/doublestar v1.1.1 // indirect + github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 // indirect github.com/cf-stratos/mysqlstore v0.0.0-20170822100912-304308519d13 github.com/charlievieth/fs v0.0.0-20170613215519-7dc373669fa1 // indirect github.com/cloudfoundry-community/go-cfenv v1.17.0 @@ -24,13 +31,18 @@ require ( github.com/cppforlife/go-patch v0.2.0 // indirect github.com/cyphar/filepath-securejoin v0.2.2 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/docker v1.13.1 // indirect github.com/domodwyer/mailyak v3.1.1+incompatible github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 // indirect + github.com/elazarl/goproxy v0.0.0-20200315184450-1f3cb6622dad // indirect + github.com/elazarl/goproxy/ext v0.0.0-20200315184450-1f3cb6622dad // indirect github.com/fatih/color v1.7.0 // indirect github.com/go-sql-driver/mysql v1.4.1 github.com/gogo/protobuf v1.2.1 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/google/go-querystring v1.0.0 // indirect + github.com/google/martian v2.1.0+incompatible // indirect github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e // indirect github.com/gorilla/context v1.1.1 github.com/gorilla/securecookie v1.1.1 @@ -40,7 +52,8 @@ require ( github.com/jessevdk/go-flags v1.4.0 // indirect github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/kat-co/vala v0.0.0-20170210184112-42e1d8b61f12 - github.com/kubeapps/common v0.0.0-20181107174310-61d8eb6f11b4 + github.com/kr/pty v1.1.8 // indirect + github.com/kubeapps/common v0.0.0-20181107174310-61d8eb6f11b4 // indirect github.com/kylelemons/go-gypsy v0.0.0-20160905020020-08cad365cd28 // indirect github.com/labstack/echo v3.3.10+incompatible github.com/labstack/gommon v0.3.0 // indirect @@ -59,12 +72,18 @@ require ( github.com/nwmac/sqlitestore v0.0.0-20180824125213-7d2ab221fb3f github.com/onsi/ginkgo v1.11.0 // indirect github.com/onsi/gomega v1.8.1 // indirect + github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/pierrec/lz4 v2.0.5+incompatible // indirect github.com/pkg/errors v0.8.1 // indirect + github.com/poy/eachers v0.0.0-20181020210610-23942921fe77 // indirect + github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 // indirect + github.com/sajari/fuzzy v1.0.0 // indirect github.com/satori/go.uuid v1.2.0 github.com/sirupsen/logrus v1.3.0 github.com/smartystreets/assertions v0.0.0-20190401211740-f487f9de1cd3 // indirect github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa + github.com/tedsuo/ifrit v0.0.0-20191009134036-9a97d0632f00 // indirect + github.com/tedsuo/rata v1.0.0 // indirect github.com/ulikunitz/xz v0.5.6 // indirect github.com/valyala/fasttemplate v1.1.0 // indirect github.com/vito/go-interact v0.0.0-20171111012221-fa338ed9e9ec // indirect diff --git a/src/jetstream/go.sum b/src/jetstream/go.sum index 85168fd7fd..494c818e50 100644 --- a/src/jetstream/go.sum +++ b/src/jetstream/go.sum @@ -4,10 +4,22 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= code.cloudfoundry.org/bytefmt v0.0.0-20180906201452-2aa6f33b730c h1:VzwteSWGbW9mxXTEkH+kpnao5jbgLynw3hq742juQh8= code.cloudfoundry.org/bytefmt v0.0.0-20180906201452-2aa6f33b730c/go.mod h1:wN/zk7mhREp/oviagqUXY3EwuHhWyOvAdsn5Y4CzOrc= +code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6 h1:Yc9r1p21kEpni9WlG4mwOZw87TB2QlyS9sAEebZ3+ak= +code.cloudfoundry.org/cfnetworking-cli-api v0.0.0-20190103195135-4b04f26287a6/go.mod h1:u5FovqC5GGAEbFPz+IdjycDA+gIjhUwqxnu0vbHwVeM= code.cloudfoundry.org/cli v6.43.0+incompatible h1:jAaPyHN5Hb2r2sR9i8Y8ejKPiPpuBYMaHBFyKVmQ7T4= code.cloudfoundry.org/cli v6.43.0+incompatible/go.mod h1:e4d+EpbwevNhyTZKybrLlyTvpH+W22vMsmdmcTxs/Fo= +code.cloudfoundry.org/cli v6.49.0+incompatible h1:lUuYux9EXLe8EBzlvckJLpHKhc8szJfWiEc3SXdM8+o= +code.cloudfoundry.org/cli v6.49.0+incompatible/go.mod h1:e4d+EpbwevNhyTZKybrLlyTvpH+W22vMsmdmcTxs/Fo= +code.cloudfoundry.org/diego-ssh v0.0.0-20200312183824-517d22c5d890 h1:sr3sHuZSH6puBqQgatzM3hYRrfOc+D8eVv0ykLYwd6o= +code.cloudfoundry.org/diego-ssh v0.0.0-20200312183824-517d22c5d890/go.mod h1:L2/glHnSK+wKnsG8oZZqdV2sgYY9NDo/I1aDJGhcWaM= code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f h1:UrKzEwTgeiff9vxdrfdqxibzpWjxLnuXDI5m6z3GJAk= code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f/go.mod h1:sk5LnIjB/nIEU7yP5sDQExVm62wu0pBh3yrElngUisI= +code.cloudfoundry.org/inigo v0.0.0-20200318144131-597cd5dbfe8b h1:TSoj8216L9LEU1MKAI9GSpOpLesalhitn8R4fEn38P8= +code.cloudfoundry.org/inigo v0.0.0-20200318144131-597cd5dbfe8b/go.mod h1:1ZB1JCh2FAp+SqX79ve6dc8YREvbsziULEOncAilX4Q= +code.cloudfoundry.org/lager v2.0.0+incompatible h1:WZwDKDB2PLd/oL+USK4b4aEjUymIej9My2nUQ9oWEwQ= +code.cloudfoundry.org/lager v2.0.0+incompatible/go.mod h1:O2sS7gKP3HM2iemG+EnwvyNQK7pTSC6Foi4QiMp9sSk= +code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d h1:M+zXqtXJqcsmpL76aU0tdl1ho23eYa4axYoM4gD62UA= +code.cloudfoundry.org/ykk v0.0.0-20170424192843-e4df4ce2fd4d/go.mod h1:YUJiVOr5xl0N/RjMxM1tHmgSpBbi5UM+KoVR5AoejO0= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= @@ -32,6 +44,8 @@ github.com/SermoDigital/jose v0.9.2-0.20180104203859-803625baeddc h1:MhBvG7RLaLq github.com/SermoDigital/jose v0.9.2-0.20180104203859-803625baeddc/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA= github.com/antonlindstrom/pgstore v0.0.0-20170604072116-a407030ba6d0 h1:e6PEaXbztY0ViaKotCICNnBQDUeNEJgrQ5UAHWlloh4= github.com/antonlindstrom/pgstore v0.0.0-20170604072116-a407030ba6d0/go.mod h1:2Ti6VUHVxpC0VSmTZzEvpzysnaGAfGBOoMIz5ykPyyw= +github.com/apoydence/eachers v0.0.0-20181020210610-23942921fe77 h1:afT88tB6u9JCKQZVAAaa9ICz/uGn5Uw9ekn6P22mYKM= +github.com/apoydence/eachers v0.0.0-20181020210610-23942921fe77/go.mod h1:bXvGk6IkT1Agy7qzJ+DjIw/SJ1AaB3AvAuMDVV+Vkoo= github.com/arschles/assert v1.0.0/go.mod h1:m/u69zW43x0h8dTHcv3JJZljINyEYgBuf5fYJP6WikI= github.com/aws/aws-sdk-go v1.17.5 h1:WW9Hm3KYo48iZHpmBc+b7sgyS0h32zgCvya28SLW4BU= github.com/aws/aws-sdk-go v1.17.5/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -41,6 +55,8 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/cf-stratos/mysqlstore v0.0.0-20170822100912-304308519d13 h1:WwIvjUUodNoZduhdhotbKnrLSFoIn5vD3QgNZv0hjvo= github.com/cf-stratos/mysqlstore v0.0.0-20170822100912-304308519d13/go.mod h1:GgQT0ToC+7JLnMKdDB5d434WwCLC2dpNR2AgTJj/08o= github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 h1:HD4PLRzjuCVW79mQ0/pdsalOLHJ+FaEoqJLxfltpb2U= @@ -50,6 +66,7 @@ github.com/charlievieth/fs v0.0.0-20170613215519-7dc373669fa1/go.mod h1:sAoA1zHC github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudfoundry-community/go-cfenv v1.17.0 h1:qfxEfn8qKkaHY3ZEk/Y2noY79HBASvNgmtHK9x4+6GY= github.com/cloudfoundry-community/go-cfenv v1.17.0/go.mod h1:2UgWvQTRXUuIZ/x3KnW6fk6CgPBhcV4UQb/UGIrUyyI= +github.com/cloudfoundry-incubator/stratos v2.0.0-beta-001+incompatible h1:UUxNbLjhv2cfymub5yNN1tjjqYkteHBBagb4jcbXEIQ= github.com/cloudfoundry/bosh-cli v5.4.0+incompatible h1:KpT2PBB7nP1QnK8guXeZ/D2k7FZYAOxcveKgYTDEDBI= github.com/cloudfoundry/bosh-cli v5.4.0+incompatible/go.mod h1:rzIB+e1sn7wQL/TJ54bl/FemPKRhXby5BIMS3tLuWFM= github.com/cloudfoundry/bosh-utils v0.0.0-20190206192830-9a0affed2bf1 h1:TxcGamw+BaxXTFwZFORzkWNMCHAWjhThxnI24CLS7iE= @@ -62,6 +79,8 @@ github.com/cloudfoundry/sonde-go v0.0.0-20171206171820-b33733203bb4 h1:cWfya7mo/ github.com/cloudfoundry/sonde-go v0.0.0-20171206171820-b33733203bb4/go.mod h1:GS0pCHd7onIsewbw8Ue9qa9pZPv2V88cUZDttK6KzgI= github.com/cppforlife/go-patch v0.2.0 h1:Y14MnCQjDlbw7WXT4k+u6DPAA9XnygN4BfrSpI/19RU= github.com/cppforlife/go-patch v0.2.0/go.mod h1:67a7aIi94FHDZdoeGSJRRFDp66l9MhaAG1yGxpUoFD8= +github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -81,12 +100,18 @@ github.com/domodwyer/mailyak v3.1.1+incompatible h1:oPtXn3+56LEFbdqH0bpuPRsqtijW github.com/domodwyer/mailyak v3.1.1+incompatible/go.mod h1:5NNYkn9hxcdNEOmmMx0yultN5VLorZQ+AWQo9iya+UY= github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 h1:eX+pdPPlD279OWgdx7f6KqIRSONuK7egk+jDx7OM3Ac= github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76/go.mod h1:KjxHHirfLaw19iGT70HvVjHQsL1vq1SRQB4yOsAfy2s= +github.com/elazarl/goproxy v0.0.0-20200315184450-1f3cb6622dad h1:zPs0fNF2Io1Qytf92EI2CDJ9oCXZr+NmjEVexrUEdq4= +github.com/elazarl/goproxy v0.0.0-20200315184450-1f3cb6622dad/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= +github.com/elazarl/goproxy/ext v0.0.0-20200315184450-1f3cb6622dad h1:3OG8xVCbdeebrE5IsoWl0TP25DWiHDbLUy+EKif7hDE= +github.com/elazarl/goproxy/ext v0.0.0-20200315184450-1f3cb6622dad/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/evanphx/json-patch v4.1.0+incompatible h1:K1MDoo4AZ4wU0GIU/fPmtZg7VpzLjCxu+UwBD1FvwOc= github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -120,6 +145,8 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= @@ -173,6 +200,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kubeapps/common v0.0.0-20181107174310-61d8eb6f11b4 h1:wdTBUArlqtBYGN2Dd4+zsaFxFH0m4iGCHToW10jPX0k= github.com/kubeapps/common v0.0.0-20181107174310-61d8eb6f11b4/go.mod h1:TsgmjeDpbftqhwPKInJ3v+l+xbHs4goiB6DFb2WqY9c= github.com/kylelemons/go-gypsy v0.0.0-20160905020020-08cad365cd28 h1:mkl3tvPHIuPaWsLtmHTybJeoVEW7cbePK73Ir8VtruA= @@ -247,6 +276,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/poy/eachers v0.0.0-20181020210610-23942921fe77 h1:SNdqPRvRsVmYR0gKqFvrUKhFizPJ6yDiGQ++VAJIoDg= +github.com/poy/eachers v0.0.0-20181020210610-23942921fe77/go.mod h1:x1vqpbcMW9T/KRcQ4b48diSiSVtYgvwQ5xzDByEg4WE= github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= @@ -255,8 +286,13 @@ github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jO github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0= +github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ= +github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= +github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -283,6 +319,10 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/technosophos/moniker v0.0.0-20180509230615-a5dbd03a2245/go.mod h1:O1c8HleITsZqzNZDjSNzirUGsMT0oGu9LhHKoJrqO+A= +github.com/tedsuo/ifrit v0.0.0-20191009134036-9a97d0632f00 h1:mujcChM89zOHwgZBBNr5WZ77mBXP1yR+gLThGCYZgAg= +github.com/tedsuo/ifrit v0.0.0-20191009134036-9a97d0632f00/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= +github.com/tedsuo/rata v1.0.0 h1:Sf9aZrYy6ElSTncjnGkyC2yuVvz5YJetBIUKJ4CmeKE= +github.com/tedsuo/rata v1.0.0/go.mod h1:X47ELzhOoLbfFIY0Cql9P6yo3Cdwf2CMX3FVZxRzJPc= github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/unrolled/render v1.0.0 h1:XYtvhA3UkpB7PqkvhUFYmpKD55OudoIeygcfus4vcd4= @@ -325,6 +365,7 @@ golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226191147-529b322ea346 h1:zxGQKdHVCsCsJpbd7ijKsVC27CyETheUBql7Br2TGmA= golang.org/x/oauth2 v0.0.0-20190226191147-529b322ea346/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/src/jetstream/plugins/cfapppush/app-repository.go b/src/jetstream/plugins/cfapppush/app-repository.go deleted file mode 100644 index f75e5749fe..0000000000 --- a/src/jetstream/plugins/cfapppush/app-repository.go +++ /dev/null @@ -1,75 +0,0 @@ -package cfapppush - -import ( - "code.cloudfoundry.org/cli/cf/api/applications" - "code.cloudfoundry.org/cli/cf/models" - - "github.com/gorilla/websocket" -) - -// RepositoryIntercept allows us to intercept application creation within the push process -type RepositoryIntercept struct { - target applications.Repository - msgSender DeployAppMessageSender - clientWebsocket *websocket.Conn -} - -// NewRepositoryIntercept creates a new RepositoryIntercept based on the supplied parameters -func NewRepositoryIntercept(target applications.Repository, msgSender DeployAppMessageSender, clientWebsocket *websocket.Conn) (repo RepositoryIntercept) { - repo.target = target - repo.msgSender = msgSender - repo.clientWebsocket = clientWebsocket - return -} - -func (repo RepositoryIntercept) sendAppData(app models.Application) { - repo.msgSender.SendEvent(repo.clientWebsocket, APP_GUID_NOTIFY, app.GUID) -} - -// Create proxies the Create method from models.Application, notifying the application -func (repo RepositoryIntercept) Create(params models.AppParams) (models.Application, error) { - app, err := repo.target.Create(params) - if err == nil { - repo.sendAppData(app) - } - return app, err -} - -// GetApp proxies the GetApp method from models.Application -func (repo RepositoryIntercept) GetApp(appGUID string) (app models.Application, apiErr error) { - return repo.target.GetApp(appGUID) -} - -// Read proxies the Read method from models.Application, notifying the application -func (repo RepositoryIntercept) Read(name string) (app models.Application, apiErr error) { - app, err := repo.target.Read(name) - if err == nil { - repo.sendAppData(app) - } - return app, err -} - -// ReadFromSpace proxies the ReadFromSpace method from models.Application -func (repo RepositoryIntercept) ReadFromSpace(name string, spaceGUID string) (app models.Application, apiErr error) { - return repo.target.ReadFromSpace(name, spaceGUID) -} - -// Update proxies the Update method from models.Application -func (repo RepositoryIntercept) Update(appGUID string, params models.AppParams) (updatedApp models.Application, apiErr error) { - return repo.target.Update(appGUID, params) -} - -// Delete proxies the Delete method from models.Application -func (repo RepositoryIntercept) Delete(appGUID string) (apiErr error) { - return repo.target.Delete(appGUID) -} - -// ReadEnv proxies the ReadEnv method from models.Application -func (repo RepositoryIntercept) ReadEnv(guid string) (*models.Environment, error) { - return repo.target.ReadEnv(guid) -} - -// CreateRestageRequest proxies the CreateRestageRequest method from models.Application -func (repo RepositoryIntercept) CreateRestageRequest(guid string) error { - return repo.target.CreateRestageRequest(guid) -} diff --git a/src/jetstream/plugins/cfapppush/deploy.go b/src/jetstream/plugins/cfapppush/deploy.go index b27c3b8bc0..0bdc453ddb 100644 --- a/src/jetstream/plugins/cfapppush/deploy.go +++ b/src/jetstream/plugins/cfapppush/deploy.go @@ -10,7 +10,6 @@ import ( "strings" "time" - "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/cfapppush/pushapp" "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" "github.com/gorilla/websocket" "github.com/labstack/echo" @@ -72,11 +71,6 @@ const ( stratosProjectKey = "STRATOS_PROJECT" ) -// DeployAppMessageSender is the interface for sending a message over a web socket -type DeployAppMessageSender interface { - SendEvent(clientWebSocket *websocket.Conn, event MessageType, data string) -} - func (cfAppPush *CFAppPush) deploy(echoContext echo.Context) error { cnsiGUID := echoContext.Param("cnsiGuid") @@ -85,6 +79,9 @@ func (cfAppPush *CFAppPush) deploy(echoContext echo.Context) error { spaceName := echoContext.QueryParam("space") orgName := echoContext.QueryParam("org") + // App ID is this is a redeploy + appID := echoContext.QueryParam("app") + clientWebSocket, pingTicker, err := interfaces.UpgradeToWebSocket(echoContext) if err != nil { log.Errorf("Upgrade to websocket failed due to: %+v", err) @@ -155,7 +152,7 @@ func (cfAppPush *CFAppPush) deploy(echoContext echo.Context) error { } log.Debugf("Overrides: %v+", msgOverrides) - overrides := pushapp.CFPushAppOverrides{} + overrides := CFPushAppOverrides{} if err = json.Unmarshal([]byte(msgOverrides.Message), &overrides); err != nil { log.Errorf("Error marshalling json: %v+", err) return err @@ -190,18 +187,17 @@ func (cfAppPush *CFAppPush) deploy(echoContext echo.Context) error { return err } + // Send App ID now if we have it (redeploy) + if len(appID) > 0 { + cfAppPush.SendEvent(clientWebSocket, APP_GUID_NOTIFY, appID) + } + dialTimeout := cfAppPush.portalProxy.Env().String("CF_DIAL_TIMEOUT", "") pushConfig.OutputWriter = socketWriter pushConfig.DialTimeout = dialTimeout // Initialise Push Command - cfAppPush.cfPush = pushapp.Constructor(pushConfig) - - // Patch in app repo watcher - // Wrap an interceptor around the application repository so we can get the app details when created/updated - deps := cfAppPush.cfPush.GetDeps() - var repo = deps.RepoLocator.GetApplicationRepository() - cfAppPush.cfPush.PatchApplicationRepository(NewRepositoryIntercept(repo, cfAppPush, clientWebSocket)) + cfAppPush.cfPush = Constructor(pushConfig, cfAppPush.portalProxy) err = cfAppPush.cfPush.Init(appDir, manifestFile, overrides) if err != nil { @@ -211,7 +207,8 @@ func (cfAppPush *CFAppPush) deploy(echoContext echo.Context) error { } sendEvent(clientWebSocket, EVENT_PUSH_STARTED) - err = cfAppPush.cfPush.Push() + + err = cfAppPush.cfPush.Run(cfAppPush, clientWebSocket) if err != nil { log.Warnf("Failed to execute due to: %+v", err) sendErrorMessage(clientWebSocket, err, CLOSE_PUSH_ERROR) @@ -466,7 +463,7 @@ func getMarshalledSocketMessage(data string, messageType MessageType) ([]byte, e return marshalledJSON, err } -func (cfAppPush *CFAppPush) getConfigData(echoContext echo.Context, cnsiGUID string, orgGUID string, spaceGUID string, spaceName string, orgName string, clientWebSocket *websocket.Conn) (*pushapp.CFPushAppConfig, error) { +func (cfAppPush *CFAppPush) getConfigData(echoContext echo.Context, cnsiGUID string, orgGUID string, spaceGUID string, spaceName string, orgName string, clientWebSocket *websocket.Conn) (*CFPushAppConfig, error) { cnsiRecord, err := cfAppPush.portalProxy.GetCNSIRecord(cnsiGUID) if err != nil { @@ -489,7 +486,7 @@ func (cfAppPush *CFAppPush) getConfigData(echoContext echo.Context, cnsiGUID str return nil, errors.New("Failed to find token record") } - config := &pushapp.CFPushAppConfig{ + config := &CFPushAppConfig{ AuthorizationEndpoint: cnsiRecord.AuthorizationEndpoint, CFClient: cnsiRecord.ClientId, CFClientSecret: cnsiRecord.ClientSecret, @@ -596,7 +593,7 @@ func fetchManifest(repoPath string, stratosProject StratosProject, clientWebSock if len(envVarMetaData) > 0 { for i, app := range manifest.Applications { if len(app.EnvironmentVariables) == 0 { - app.EnvironmentVariables = make(map[string]interface{}) + app.EnvironmentVariables = make(map[string]string) } app.EnvironmentVariables[stratosProjectKey] = envVarMetaData manifest.Applications[i] = app diff --git a/src/jetstream/plugins/cfapppush/info.go b/src/jetstream/plugins/cfapppush/info.go new file mode 100644 index 0000000000..c32b34cc2c --- /dev/null +++ b/src/jetstream/plugins/cfapppush/info.go @@ -0,0 +1,38 @@ +package cfapppush + +import ( + "errors" + + "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" + + "code.cloudfoundry.org/cli/util/configv3" + log "github.com/sirupsen/logrus" +) + +// Get the Cloud Foundry Info +func (c *CFPushApp) setEndpointInfo(config *configv3.Config) error { + log.Debug("CF Push Get CF Info") + + apiEndpoint := c.config.APIEndpointURL + skipSSLValidation := c.config.SkipSSLValidation + + cfEndpointSpec, err := c.portalProxy.GetEndpointTypeSpec("cf") + if err != nil { + return err + } + + _, endpointInfo, err := cfEndpointSpec.Info(apiEndpoint, skipSSLValidation) + if err != nil { + return err + } + + if info, ok := endpointInfo.(interfaces.V2Info); ok { + // Got the info we need - update the config with it + config.SetTargetInformation(apiEndpoint, info.APIVersion, info.AuthorizationEndpoint, info.MinCLIVersion, info.DopplerLoggingEndpoint, info.RoutingEndpoint, skipSSLValidation) + config.SetAccessToken("bearer " + c.config.AuthToken) + } else { + return errors.New("Did not get a CF /v2/info response") + } + + return nil +} diff --git a/src/jetstream/plugins/cfapppush/main.go b/src/jetstream/plugins/cfapppush/main.go index 605db754c9..25a3596697 100644 --- a/src/jetstream/plugins/cfapppush/main.go +++ b/src/jetstream/plugins/cfapppush/main.go @@ -3,7 +3,6 @@ package cfapppush import ( "errors" - "github.com/cloudfoundry-incubator/stratos/src/jetstream/plugins/cfapppush/pushapp" "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" "github.com/labstack/echo" ) @@ -11,7 +10,7 @@ import ( // CFAppPush is a plugin to allow applications to be pushed to Cloud Foundry from Stratos type CFAppPush struct { portalProxy interfaces.PortalProxy - cfPush pushapp.CFPush + cfPush CFPush } // Init creates a new CFAppPush diff --git a/src/jetstream/plugins/cfapppush/progress_bar.go b/src/jetstream/plugins/cfapppush/progress_bar.go new file mode 100644 index 0000000000..eeaa687eee --- /dev/null +++ b/src/jetstream/plugins/cfapppush/progress_bar.go @@ -0,0 +1,17 @@ +package cfapppush + +import ( + "io" +) + +// Fake progress bar - don't want to show progress in backend logs +// We could add support for sending this to the client and having a nicer UI there +type cfPushProgressBar struct{} + +func (t *cfPushProgressBar) Ready() {} + +func (t *cfPushProgressBar) Complete() {} + +func (t *cfPushProgressBar) NewProgressBarWrapper(reader io.Reader, sizeOfFile int64) io.Reader { + return reader +} diff --git a/src/jetstream/plugins/cfapppush/push_actor.go b/src/jetstream/plugins/cfapppush/push_actor.go new file mode 100644 index 0000000000..3953f3c928 --- /dev/null +++ b/src/jetstream/plugins/cfapppush/push_actor.go @@ -0,0 +1,112 @@ +package cfapppush + +import ( + "io" + + "code.cloudfoundry.org/cli/actor/pushaction" + "code.cloudfoundry.org/cli/actor/v2action" + "github.com/gorilla/websocket" +) + +type cfV2Actor struct { + wrapped pushaction.V2Actor + sent bool + msgSender DeployAppMessageSender + clientWebsocket *websocket.Conn +} + +func (r cfV2Actor) sendAppID(application v2action.Application) { + if !r.sent { + r.msgSender.SendEvent(r.clientWebsocket, APP_GUID_NOTIFY, application.GUID) + r.sent = true + } +} + +func (r cfV2Actor) MapRouteToApplication(routeGUID string, appGUID string) (v2action.Warnings, error) { + return r.wrapped.MapRouteToApplication(routeGUID, appGUID) +} + +func (r cfV2Actor) BindServiceByApplicationAndServiceInstance(appGUID string, serviceInstanceGUID string) (v2action.Warnings, error) { + return r.wrapped.BindServiceByApplicationAndServiceInstance(appGUID, serviceInstanceGUID) +} + +func (r cfV2Actor) CloudControllerAPIVersion() string { + return r.wrapped.CloudControllerAPIVersion() +} + +func (r cfV2Actor) CreateApplication(application v2action.Application) (v2action.Application, v2action.Warnings, error) { + app, warnings, err := r.wrapped.CreateApplication(application) + if err == nil { + r.sendAppID(app) + } + return app, warnings, err +} + +func (r cfV2Actor) CreateRoute(route v2action.Route, generatePort bool) (v2action.Route, v2action.Warnings, error) { + return r.wrapped.CreateRoute(route, generatePort) +} + +func (r cfV2Actor) FindRouteBoundToSpaceWithSettings(route v2action.Route) (v2action.Route, v2action.Warnings, error) { + return r.wrapped.FindRouteBoundToSpaceWithSettings(route) +} + +func (r cfV2Actor) GetApplicationByNameAndSpace(name string, spaceGUID string) (v2action.Application, v2action.Warnings, error) { + app, warnings, err := r.wrapped.GetApplicationByNameAndSpace(name, spaceGUID) + if err == nil { + r.sendAppID(app) + } + return app, warnings, err +} + +func (r cfV2Actor) GetApplicationRoutes(applicationGUID string) (v2action.Routes, v2action.Warnings, error) { + return r.wrapped.GetApplicationRoutes(applicationGUID) +} + +func (r cfV2Actor) GetDomainsByNameAndOrganization(domainNames []string, orgGUID string) ([]v2action.Domain, v2action.Warnings, error) { + return r.wrapped.GetDomainsByNameAndOrganization(domainNames, orgGUID) +} + +func (r cfV2Actor) GetOrganizationDomains(orgGUID string) ([]v2action.Domain, v2action.Warnings, error) { + return r.wrapped.GetOrganizationDomains(orgGUID) +} + +func (r cfV2Actor) GetServiceInstanceByNameAndSpace(name string, spaceGUID string) (v2action.ServiceInstance, v2action.Warnings, error) { + return r.wrapped.GetServiceInstanceByNameAndSpace(name, spaceGUID) +} + +func (r cfV2Actor) GetServiceInstancesByApplication(appGUID string) ([]v2action.ServiceInstance, v2action.Warnings, error) { + return r.wrapped.GetServiceInstancesByApplication(appGUID) +} + +func (r cfV2Actor) GetStack(guid string) (v2action.Stack, v2action.Warnings, error) { + return r.wrapped.GetStack(guid) +} + +func (r cfV2Actor) GetStackByName(stackName string) (v2action.Stack, v2action.Warnings, error) { + return r.wrapped.GetStackByName(stackName) +} + +func (r cfV2Actor) PollJob(job v2action.Job) (v2action.Warnings, error) { + return r.wrapped.PollJob(job) +} + +func (r cfV2Actor) ResourceMatch(allResources []v2action.Resource) ([]v2action.Resource, []v2action.Resource, v2action.Warnings, error) { + return r.wrapped.ResourceMatch(allResources) +} + +func (r cfV2Actor) UnmapRouteFromApplication(routeGUID string, appGUID string) (v2action.Warnings, error) { + return r.wrapped.UnmapRouteFromApplication(routeGUID, appGUID) +} + +func (r cfV2Actor) UpdateApplication(application v2action.Application) (v2action.Application, v2action.Warnings, error) { + r.sendAppID(application) + return r.wrapped.UpdateApplication(application) +} + +func (r cfV2Actor) UploadApplicationPackage(appGUID string, existingResources []v2action.Resource, newResources io.Reader, newResourcesLength int64) (v2action.Job, v2action.Warnings, error) { + return r.wrapped.UploadApplicationPackage(appGUID, existingResources, newResources, newResourcesLength) +} + +func (r cfV2Actor) UploadDroplet(appGUID string, droplet io.Reader, dropletLength int64) (v2action.Job, v2action.Warnings, error) { + return r.wrapped.UploadDroplet(appGUID, droplet, dropletLength) +} diff --git a/src/jetstream/plugins/cfapppush/pushapp.go b/src/jetstream/plugins/cfapppush/pushapp.go new file mode 100644 index 0000000000..11a1c00976 --- /dev/null +++ b/src/jetstream/plugins/cfapppush/pushapp.go @@ -0,0 +1,401 @@ +package cfapppush + +import ( + "bytes" + "encoding/json" + "errors" + + "fmt" + "html/template" + "io" + "strings" + + "code.cloudfoundry.org/cli/actor/pushaction" + "code.cloudfoundry.org/cli/actor/sharedaction" + "code.cloudfoundry.org/cli/actor/v2action" + "code.cloudfoundry.org/cli/actor/v2v3action" + "code.cloudfoundry.org/cli/actor/v3action" + "code.cloudfoundry.org/cli/cf/commandregistry" + "code.cloudfoundry.org/cli/command" + + "code.cloudfoundry.org/cli/util/configv3" + "code.cloudfoundry.org/cli/util/progressbar" + "code.cloudfoundry.org/cli/util/ui" + "github.com/gorilla/websocket" + + "code.cloudfoundry.org/cli/cf/flags" + + "code.cloudfoundry.org/cli/command/flag" + "code.cloudfoundry.org/cli/command/translatableerror" + v6 "code.cloudfoundry.org/cli/command/v6" + "code.cloudfoundry.org/cli/command/v6/shared" + sharedV3 "code.cloudfoundry.org/cli/command/v6/shared" + + "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/interfaces" +) + +// CFPushApp abstracts the push functionality form the CLI library +type CFPushApp struct { + pushCommand *v6.PushCommand + flagContext flags.FlagContext + deps commandregistry.Dependency + config *CFPushAppConfig + portalProxy interfaces.PortalProxy +} + +// CFPushAppConfig is the configuration used +type CFPushAppConfig struct { + AuthorizationEndpoint string + CFClient string + CFClientSecret string + APIEndpointURL string + DopplerLoggingEndpoint string + SkipSSLValidation bool + AuthToken string + RefreshToken string + OrgGUID string + OrgName string + SpaceGUID string + SpaceName string + OutputWriter io.Writer + DialTimeout string +} + +// CFPushAppOverrides represents the document that can be sent from the client with the app overrrides for the push +type CFPushAppOverrides struct { + Name string `json:"name"` + Buildpack string `json:"buildpack"` + StartCmd string `json:"startCmd"` + HealthCheckType string `json:"healthCheckType"` + Stack string `json:"stack"` + Time *int `json:"time"` + Instances *int `json:"instances"` + DiskQuota string `json:"diskQuota"` + MemQuota string `json:"memQuota"` + DoNotStart bool `json:"doNotStart"` + NoRoute bool `json:"noRoute"` + RandomRoute bool `json:"randomRoute"` + Host string `json:"host"` + Domain string `json:"domain"` + Path string `json:"path"` + DockerImage string `json:"dockerImage"` + DockerUsername string `json:"dockerUsername"` +} + +// DeployAppMessageSender is the interface for sending a message over a web socket +type DeployAppMessageSender interface { + SendEvent(clientWebSocket *websocket.Conn, event MessageType, data string) +} + +// ErrorType default error returned +type ErrorType int + +const ( + // GeneralFailure thrown when initialisation fails + GeneralFailure ErrorType = iota + 4000 + // FailedToPush thrown when push fails + FailedToPush +) + +// CFPush Interface +type CFPush interface { + Init(appDir string, manifestPath string, overrides CFPushAppOverrides) error + Run(DeployAppMessageSender, *websocket.Conn) error +} + +// PushError is the return error type from pushing +type PushError struct { + error + Type ErrorType + Err error +} + +func (p *PushError) Error() string { + return fmt.Sprintf("Push error: %s", p.Err) +} + +// Constructor returns a CFPush based on the supplied config +func Constructor(config *CFPushAppConfig, portalProxy interfaces.PortalProxy) CFPush { + + pushCmd := &v6.PushCommand{} + cfPush := &CFPushApp{ + pushCommand: pushCmd, + config: config, + portalProxy: portalProxy, + } + cfPush.init(config) + return cfPush +} + +func (c *CFPushApp) init(config *CFPushAppConfig) error { + return nil +} + +// Init initializes the push operation with the specified application directory and manifest path +func (c *CFPushApp) Init(appDir string, manifestPath string, overrides CFPushAppOverrides) error { + + // App name + if len(overrides.Name) > 0 { + c.pushCommand.OptionalArgs = flag.OptionalAppName{ + AppName: overrides.Name, + } + } + + // Buildpack - Note we only allow one buildpack to be specified as an override at present + if len(overrides.Buildpack) > 0 { + c.pushCommand.Buildpacks = make([]string, 1) + c.pushCommand.Buildpacks[0] = overrides.Buildpack + } + + // Start Command + if len(overrides.StartCmd) > 0 { + c.pushCommand.Command = flag.Command{} + err := c.pushCommand.Command.UnmarshalFlag(overrides.StartCmd) + if err != nil { + return err + } + } + + // Domain + if len(overrides.Domain) > 0 { + c.pushCommand.Domain = overrides.Domain + } + + // HealthCheckType + if len(overrides.HealthCheckType) > 0 { + err := c.pushCommand.HealthCheckType.UnmarshalFlag(overrides.HealthCheckType) + if err != nil { + return err + } + } + + // Hostname + if len(overrides.Host) > 0 { + c.pushCommand.Hostname = overrides.Host + } + + // App instances + if overrides.Instances != nil { + c.pushCommand.Instances = flag.Instances{} + c.pushCommand.Instances.ParseIntValue(overrides.Instances) + } + + // Disk Quota + if len(overrides.DiskQuota) > 0 { + c.pushCommand.DiskQuota = flag.Megabytes{} + err := c.pushCommand.DiskQuota.UnmarshalFlag(overrides.DiskQuota) + if err != nil { + return err + } + } + + // Memory Quota + if len(overrides.MemQuota) > 0 { + c.pushCommand.Memory = flag.Megabytes{} + err := c.pushCommand.Memory.UnmarshalFlag(overrides.MemQuota) + if err != nil { + return err + } + } + + // No Route + c.pushCommand.NoRoute = overrides.NoRoute + + // No start + c.pushCommand.NoStart = overrides.DoNotStart + + // Random route + c.pushCommand.RandomRoute = overrides.RandomRoute + + // Route path + if len(overrides.Path) > 0 { + c.pushCommand.RoutePath = flag.V6RoutePath{} + err := c.pushCommand.RoutePath.UnmarshalFlag(overrides.Path) + if err != nil { + return err + } + } + + // Stack + if len(overrides.Stack) > 0 { + c.pushCommand.StackName = overrides.Stack + } + + // Health check time + if overrides.Time != nil { + c.pushCommand.HealthCheckTimeout = uint64(*overrides.Time) + } + + // Docker image + if len(overrides.DockerImage) > 0 { + c.pushCommand.DockerImage = flag.DockerImage{ + Path: overrides.DockerImage, + } + } else { + // App path can't be set with Docker Image + c.pushCommand.AppPath = flag.PathWithExistenceCheck(appDir) + } + + // Docker username + if len(overrides.DockerUsername) > 0 { + c.pushCommand.DockerUsername = overrides.DockerUsername + } + + // Manifest path + c.pushCommand.PathToManifest = flag.PathWithExistenceCheck(manifestPath) + + return nil +} + +// setConfig sets the org and space information +func (c *CFPushApp) setConfig(config *configv3.Config) error { + config.SetOrganizationInformation(c.config.OrgGUID, c.config.OrgName) + config.SetSpaceInformation(c.config.SpaceGUID, c.config.SpaceName, false) + return nil +} + +// Run performs the actual push +func (c *CFPushApp) Run(msgSender DeployAppMessageSender, clientWebsocket *websocket.Conn) error { + + // Get a CF Config + config, err := configv3.LoadConfig() + if err != nil { + return err + } + + // Fetch and set endpoint info + err = c.setEndpointInfo(config) + if err != nil { + return err + } + + commandUI, err := ui.NewUI(config) + if err != nil { + return err + } + + commandUI.IsTTY = false + commandUI.TerminalWidth = 40 + + // Send logging to the front-end via the web-socket + commandUI.Out = c.config.OutputWriter + commandUI.Err = c.config.OutputWriter + + defer commandUI.FlushDeferred() + + err = c.setup(config, commandUI, msgSender, clientWebsocket) + //err = c.pushCommand.Setup(config, commandUI) + if err != nil { + return handleError(err, *commandUI) + } + + // Update the config + err = c.setConfig(config) + if err != nil { + return handleError(err, *commandUI) + } + + // Set to a null progress bar + c.pushCommand.ProgressBar = &cfPushProgressBar{} + + // Perform the push + args := make([]string, 0) + err = c.pushCommand.Execute(args) + if err != nil { + return handleError(err, *commandUI) + } + + return nil +} + +func (push *CFPushApp) setup(config command.Config, ui command.UI, msgSender DeployAppMessageSender, clientWebsocket *websocket.Conn) error { + cmd := push.pushCommand + cmd.UI = ui + cmd.Config = config + sharedActor := sharedaction.NewActor(config) + cmd.SharedActor = sharedActor + + ccClient, uaaClient, err := shared.GetNewClientsAndConnectToCF(config, ui) + if err != nil { + return err + } + + ccClientV3, _, err := sharedV3.NewV3BasedClients(config, ui, true) + if err != nil { + return err + } + + v2Actor := v2action.NewActor(ccClient, uaaClient, config) + v3Actor := v3action.NewActor(ccClientV3, config, sharedActor, nil) + + stratosV2Actor := cfV2Actor{ + wrapped: v2Actor, + msgSender: msgSender, + clientWebsocket: clientWebsocket, + } + + cmd.RestartActor = v2Actor + cmd.Actor = pushaction.NewActor(stratosV2Actor, v3Actor, sharedActor) + + cmd.ApplicationSummaryActor = v2v3action.NewActor(v2Actor, v3Actor) + + cmd.NOAAClient = shared.NewNOAAClient(ccClient.DopplerEndpoint(), config, uaaClient, ui) + + cmd.ProgressBar = progressbar.NewProgressBar() + return nil +} + +// Simplified version of the CLI source +func handleError(passedErr error, commandUI ui.UI) error { + if passedErr == nil { + return nil + } + + translationFunc, _ := generateTranslationFunc([]byte("[]")) + translatedErr := translatableerror.ConvertToTranslatableError(passedErr) + + var errMsg string + if translatableError, ok := translatedErr.(translatableerror.TranslatableError); ok { + errMsg = translatableError.Translate(translationFunc) + + // Remove the TIP that might be at the end + parts := strings.Split(errMsg, "TIP:") + errMsg = strings.TrimSpace(parts[0]) + } else { + errMsg = translatedErr.Error() + } + + return errors.New(errMsg) +} + +// Borrowed from the CLI source - its not exported, so we include it here +func generateTranslationFunc(rawTranslation []byte) (ui.TranslateFunc, error) { + var entries []ui.TranslationEntry + err := json.Unmarshal(rawTranslation, &entries) + if err != nil { + return nil, err + } + + translations := map[string]string{} + for _, entry := range entries { + translations[entry.ID] = entry.Translation + } + + return func(translationID string, args ...interface{}) string { + translated := translations[translationID] + if translated == "" { + translated = translationID + } + + var keys interface{} + if len(args) > 0 { + keys = args[0] + } + + var buffer bytes.Buffer + formattedTemplate := template.Must(template.New("Display Text").Parse(translated)) + formattedTemplate.Execute(&buffer, keys) + + return buffer.String() + }, nil +} diff --git a/src/jetstream/plugins/cfapppush/pushapp/pushapp.go b/src/jetstream/plugins/cfapppush/pushapp/pushapp.go deleted file mode 100644 index 801b79751b..0000000000 --- a/src/jetstream/plugins/cfapppush/pushapp/pushapp.go +++ /dev/null @@ -1,309 +0,0 @@ -package pushapp - -import ( - "fmt" - "io" - "os" - "path/filepath" - "strconv" - "time" - - "code.cloudfoundry.org/cli/cf/api/applications" - - "code.cloudfoundry.org/cli/cf/actors" - "code.cloudfoundry.org/cli/cf/actors/brokerbuilder" - "code.cloudfoundry.org/cli/cf/actors/planbuilder" - "code.cloudfoundry.org/cli/cf/actors/pluginrepo" - "code.cloudfoundry.org/cli/cf/actors/servicebuilder" - "code.cloudfoundry.org/cli/cf/api" - "code.cloudfoundry.org/cli/cf/appfiles" - "code.cloudfoundry.org/cli/cf/commandregistry" - "code.cloudfoundry.org/cli/cf/configuration" - "code.cloudfoundry.org/cli/cf/configuration/confighelpers" - "code.cloudfoundry.org/cli/cf/configuration/coreconfig" - "code.cloudfoundry.org/cli/cf/configuration/pluginconfig" - "code.cloudfoundry.org/cli/cf/manifest" - "code.cloudfoundry.org/cli/cf/models" - "code.cloudfoundry.org/cli/cf/net" - "code.cloudfoundry.org/cli/cf/terminal" - "code.cloudfoundry.org/cli/cf/trace" - "code.cloudfoundry.org/cli/util" - "code.cloudfoundry.org/cli/util/randomword" - uuid "github.com/satori/go.uuid" - log "github.com/sirupsen/logrus" - - "code.cloudfoundry.org/cli/cf/commands/application" - "code.cloudfoundry.org/cli/cf/flags" -) - -// CFPushApp abstracts the push functionality form the CLI library -type CFPushApp struct { - pushCommand *application.Push - flagContext flags.FlagContext - deps commandregistry.Dependency -} - -// CFPushAppConfig is the configuration used -type CFPushAppConfig struct { - AuthorizationEndpoint string - CFClient string - CFClientSecret string - APIEndpointURL string - DopplerLoggingEndpoint string - SkipSSLValidation bool - AuthToken string - RefreshToken string - OrgGUID string - OrgName string - SpaceGUID string - SpaceName string - OutputWriter io.Writer - DialTimeout string -} - -type CFPushAppOverrides struct { - Name string `json:"name"` - Buildpack string `json:"buildpack"` - StartCmd string `json:"startCmd"` - HealthCheckType string `json:"healthCheckType"` - Stack string `json:"stack"` - Time *int `json:"time"` - Instances *int `json:"instances"` - DiskQuota string `json:"diskQuota"` - MemQuota string `json:"memQuota"` - DoNotStart bool `json:"doNotStart"` - NoRoute bool `json:"noRoute"` - RandomRoute bool `json:"randomRoute"` - Host string `json:"host"` - Domain string `json:"domain"` - Path string `json:"path"` - DockerImage string `json:"dockerImage"` - DockerUsername string `json:"dockerUsername"` -} - -// ErrorType default error returned -type ErrorType int - -const ( - // GeneralFailure thrown when initialisation fails - GeneralFailure ErrorType = iota + 4000 - // FailedToPush thrown when push fails - FailedToPush -) - -// CFPush Interface -type CFPush interface { - Init(appDir string, manifestPath string, overrides CFPushAppOverrides) error - Push() error - GetDeps() commandregistry.Dependency - PatchApplicationRepository(repo applications.Repository) -} - -// PushError is the return error type from pushing -type PushError struct { - error - Type ErrorType - Err error -} - -func (p *PushError) Error() string { - return fmt.Sprintf("Push error: %s", p.Err) -} - -// Constructor returns a CFPush based on the supplied config -func Constructor(config *CFPushAppConfig) CFPush { - - pushCmd := &application.Push{} - metaData := pushCmd.MetaData() - flagContext := flags.NewFlagContext(metaData.Flags) - - cfPush := &CFPushApp{ - pushCommand: pushCmd, - flagContext: flagContext, - } - cfPush.init(config) - return cfPush - -} - -func (c *CFPushApp) init(config *CFPushAppConfig) error { - uuid := uuid.NewV4() - var filePath = fmt.Sprintf("/tmp/%s", uuid) - repo := coreconfig.NewRepositoryFromFilepath(filePath, func(error) {}) - repo.SetAuthenticationEndpoint(config.AuthorizationEndpoint) - repo.SetUAAOAuthClient(config.CFClient) - repo.SetUAAOAuthClientSecret(config.CFClientSecret) - repo.SetAPIEndpoint(config.APIEndpointURL) - repo.SetDopplerEndpoint(config.DopplerLoggingEndpoint) - repo.SetSSLDisabled(config.SkipSSLValidation) - repo.SetAccessToken(config.AuthToken) - repo.SetRefreshToken(config.RefreshToken) - repo.SetColorEnabled("true") - repo.SetOrganizationFields(models.OrganizationFields{ - GUID: config.OrgGUID, - Name: config.OrgName, - }) - repo.SetSpaceFields(models.SpaceFields{ - GUID: config.SpaceGUID, - Name: config.SpaceName, - }) - traceLogger := trace.NewLogger(os.Stdout, true) - dialTimeout := config.DialTimeout - c.deps = initialiseDependency(config.OutputWriter, traceLogger, dialTimeout, repo) - return nil -} - -func initialiseDependency(writer io.Writer, logger trace.Printer, envDialTimeout string, config coreconfig.Repository) commandregistry.Dependency { - - deps := commandregistry.Dependency{} - deps.TeePrinter = terminal.NewTeePrinter(writer) - deps.UI = terminal.NewUI(os.Stdin, writer, deps.TeePrinter, logger) - - errorHandler := func(err error) { - if err != nil { - deps.UI.Failed(fmt.Sprintf("Config error: %s", err)) - } - } - - deps.Config = config - - deps.ManifestRepo = manifest.NewDiskRepository() - deps.AppManifest = manifest.NewGenerator() - - pluginPath := filepath.Join(confighelpers.PluginRepoDir(), ".cf", "plugins") - deps.PluginConfig = pluginconfig.NewPluginConfig( - errorHandler, - configuration.NewDiskPersistor(filepath.Join(pluginPath, "config.json")), - pluginPath, - ) - - terminal.UserAskedForColors = deps.Config.ColorEnabled() - terminal.InitColorSupport() - - deps.Gateways = map[string]net.Gateway{ - "cloud-controller": net.NewCloudControllerGateway(deps.Config, time.Now, deps.UI, logger, envDialTimeout), - "uaa": net.NewUAAGateway(deps.Config, deps.UI, logger, envDialTimeout), - "routing-api": net.NewRoutingAPIGateway(deps.Config, time.Now, deps.UI, logger, envDialTimeout), - } - deps.RepoLocator = api.NewRepositoryLocator(deps.Config, deps.Gateways, logger, envDialTimeout) - - deps.PluginModels = &commandregistry.PluginModels{Application: nil} - - deps.PlanBuilder = planbuilder.NewBuilder( - deps.RepoLocator.GetServicePlanRepository(), - deps.RepoLocator.GetServicePlanVisibilityRepository(), - deps.RepoLocator.GetOrganizationRepository(), - ) - - deps.ServiceBuilder = servicebuilder.NewBuilder( - deps.RepoLocator.GetServiceRepository(), - deps.PlanBuilder, - ) - - deps.BrokerBuilder = brokerbuilder.NewBuilder( - deps.RepoLocator.GetServiceBrokerRepository(), - deps.ServiceBuilder, - ) - - deps.PluginRepo = pluginrepo.NewPluginRepo() - - deps.ServiceHandler = actors.NewServiceHandler( - deps.RepoLocator.GetOrganizationRepository(), - deps.BrokerBuilder, - deps.ServiceBuilder, - ) - - deps.ServicePlanHandler = actors.NewServicePlanHandler( - deps.RepoLocator.GetServicePlanRepository(), - deps.RepoLocator.GetServicePlanVisibilityRepository(), - deps.RepoLocator.GetOrganizationRepository(), - deps.PlanBuilder, - deps.ServiceBuilder, - ) - - deps.WordGenerator = new(randomword.Generator) - - deps.AppZipper = appfiles.ApplicationZipper{} - deps.AppFiles = appfiles.ApplicationFiles{} - - deps.RouteActor = actors.NewRouteActor(deps.UI, deps.RepoLocator.GetRouteRepository(), deps.RepoLocator.GetDomainRepository()) - deps.PushActor = actors.NewPushActor(deps.RepoLocator.GetApplicationBitsRepository(), deps.AppZipper, deps.AppFiles, deps.RouteActor) - - deps.ChecksumUtil = util.NewSha1Checksum("") - - deps.Logger = logger - - return deps - -} - -func appendFlag(flags []string, argName string, argValue string) []string { - if len(argValue) != 0 { - if len(argName) != 0 { - return append(flags, argName, argValue) - } else { - return append(flags, argValue) - } - } - return flags -} - -// Init initializes the push operation with the specified application directory and manifest path -func (c *CFPushApp) Init(appDir string, manifestPath string, overrides CFPushAppOverrides) error { - - var flags []string - - flags = appendFlag(flags, "", overrides.Name) - flags = appendFlag(flags, "-b", overrides.Buildpack) - flags = appendFlag(flags, "-c", overrides.StartCmd) - flags = appendFlag(flags, "-d", overrides.Domain) - flags = appendFlag(flags, "--health-check-type", overrides.HealthCheckType) - flags = appendFlag(flags, "--hostname", overrides.Host) - if overrides.Instances != nil { - flags = append(flags, "-i", strconv.Itoa(*overrides.Instances)) - } - flags = appendFlag(flags, "-k", overrides.DiskQuota) - flags = appendFlag(flags, "-m", overrides.MemQuota) - flags = append(flags, "--no-route", strconv.FormatBool(overrides.NoRoute)) - flags = append(flags, "--no-start", strconv.FormatBool(overrides.DoNotStart)) - flags = append(flags, "-p", appDir, "-f", manifestPath) - flags = append(flags, "--random-route", strconv.FormatBool(overrides.RandomRoute)) - flags = appendFlag(flags, "--route-path", overrides.Path) - flags = appendFlag(flags, "-s", overrides.Stack) - if overrides.Time != nil { - flags = append(flags, "-t", strconv.Itoa(*overrides.Time)) - } - flags = appendFlag(flags, "--docker-image", overrides.DockerImage) - flags = appendFlag(flags, "--docker-username", overrides.DockerUsername) - - log.Debugf("Cf Push Overrides: %v", flags) - - err := c.flagContext.Parse(flags...) - if err != nil { - return &PushError{Err: err, Type: GeneralFailure} - } - return nil -} - -// GetDeps is used to install watcher -func (c *CFPushApp) GetDeps() commandregistry.Dependency { - return c.deps -} - -// PatchApplicationRepository patches the repository locator so we can determine when the app has been created during push -func (c *CFPushApp) PatchApplicationRepository(appRepo applications.Repository) { - c.deps.RepoLocator = c.deps.RepoLocator.SetApplicationRepository(appRepo) -} - -// Push starts the actual push process -func (c *CFPushApp) Push() error { - - c.pushCommand.SetDependency(c.deps, false) - defer c.deps.Config.Close() - - err := c.pushCommand.Execute(c.flagContext) - if err != nil { - return &PushError{Err: err, Type: FailedToPush} - } - return nil -} diff --git a/src/jetstream/plugins/cfapppush/types.go b/src/jetstream/plugins/cfapppush/types.go index 34dc038dd3..650098c5e8 100644 --- a/src/jetstream/plugins/cfapppush/types.go +++ b/src/jetstream/plugins/cfapppush/types.go @@ -75,36 +75,30 @@ type MessageType int // Based on manifest.rawManifestApplicaiton type RawManifestApplication struct { - Name string `yaml:"name,omitempty"` - Buildpack string `yaml:"buildpack,omitempty"` - Command string `yaml:"command,omitempty"` - DeprecatedDomain interface{} `yaml:"domain,omitempty"` - DeprecatedDomains interface{} `yaml:"domains,omitempty"` - DeprecatedHost interface{} `yaml:"host,omitempty"` - DeprecatedHosts interface{} `yaml:"hosts,omitempty"` - DeprecatedNoHostname interface{} `yaml:"no-hostname,omitempty"` - DiskQuota string `yaml:"disk_quota,omitempty"` - Docker rawDockerInfo `yaml:"docker,omitempty"` - DropletPath string `yaml:"droplet-path,omitempty"` - EnvironmentVariables map[string]interface{} `yaml:"env,omitempty"` - HealthCheckHTTPEndpoint string `yaml:"health-check-http-endpoint,omitempty"` - HealthCheckType string `yaml:"health-check-type,omitempty"` - Instances *int `yaml:"instances,omitempty"` - Memory string `yaml:"memory,omitempty"` - NoRoute bool `yaml:"no-route,omitempty"` - Path string `yaml:"path,omitempty"` - RandomRoute bool `yaml:"random-route,omitempty"` - Routes []rawManifestRoute `yaml:"routes,omitempty"` - Services []string `yaml:"services,omitempty"` - StackName string `yaml:"stack,omitempty"` - Timeout int `yaml:"timeout,omitempty"` - DockerImage string `json:"docker_image,omitempty"` - DockerCredentials DockerCredentials `json:"docker_credentials,omitempty"` -} - -type DockerCredentials struct { - Username string `json:"username"` - Password string `json:"password"` + Name string `yaml:"name,omitempty"` + Buildpack string `yaml:"buildpack,omitempty"` + Buildpacks []string `yaml:"buildpacks,omitempty"` + Command string `yaml:"command,omitempty"` + DeprecatedDomain interface{} `yaml:"domain,omitempty"` + DeprecatedDomains interface{} `yaml:"domains,omitempty"` + DeprecatedHost interface{} `yaml:"host,omitempty"` + DeprecatedHosts interface{} `yaml:"hosts,omitempty"` + DeprecatedNoHostname interface{} `yaml:"no-hostname,omitempty"` + DiskQuota string `yaml:"disk_quota,omitempty"` + Docker rawDockerInfo `yaml:"docker,omitempty"` + DropletPath string `yaml:"droplet-path,omitempty"` + EnvironmentVariables map[string]string `yaml:"env,omitempty"` + HealthCheckHTTPEndpoint string `yaml:"health-check-http-endpoint,omitempty"` + HealthCheckType string `yaml:"health-check-type,omitempty"` + Instances *int `yaml:"instances,omitempty"` + Memory string `yaml:"memory,omitempty"` + NoRoute bool `yaml:"no-route,omitempty"` + Path string `yaml:"path,omitempty"` + RandomRoute bool `yaml:"random-route,omitempty"` + Routes []rawManifestRoute `yaml:"routes,omitempty"` + Services []string `yaml:"services,omitempty"` + StackName string `yaml:"stack,omitempty"` + Timeout int `yaml:"timeout,omitempty"` } type rawManifestRoute struct { diff --git a/src/jetstream/repository/interfaces/structs.go b/src/jetstream/repository/interfaces/structs.go index 6d6ef61d3c..041f2ebea0 100644 --- a/src/jetstream/repository/interfaces/structs.go +++ b/src/jetstream/repository/interfaces/structs.go @@ -20,6 +20,7 @@ type AuthProvider struct { UserInfo GetUserInfoFromToken } +// V2Info is the response for the Cloud Foundry /v2/info API type V2Info struct { AuthorizationEndpoint string `json:"authorization_endpoint"` TokenEndpoint string `json:"token_endpoint"` @@ -27,6 +28,10 @@ type V2Info struct { AppSSHEndpoint string `json:"app_ssh_endpoint"` AppSSHHostKeyFingerprint string `json:"app_ssh_host_key_fingerprint"` AppSSHOauthCLient string `json:"app_ssh_oauth_client"` + APIVersion string `json:"api_version"` + RoutingEndpoint string `json:"routing_endpoint"` + MinCLIVersion string `json:"min_cli_version"` + MinRecommendedCLIVersion string `json:"min_recommended_cli_version"` } type InfoFunc func(apiEndpoint string, skipSSLValidation bool) (CNSIRecord, interface{}, error) diff --git a/src/test-e2e/application/application-deploy-e2e.spec.ts b/src/test-e2e/application/application-deploy-e2e.spec.ts index b351c0ac0d..ae241e4fa8 100644 --- a/src/test-e2e/application/application-deploy-e2e.spec.ts +++ b/src/test-e2e/application/application-deploy-e2e.spec.ts @@ -209,17 +209,27 @@ describe('Application Deploy -', () => { appEvents.list.table.toggleSort('Timestamp'); const currentUser = e2e.secrets.getDefaultCFEndpoint().creds.nonAdmin.username; - // Create - expect(appEvents.list.table.getCell(0, 1).getText()).toBe('audit\napp\ncreate'); - expect(appEvents.list.table.getCell(0, 0).getText()).toBe(`person\n${currentUser}`); - // Map Route - expect(appEvents.list.table.getCell(1, 1).getText()).toBe('audit\napp\nmap-route'); - expect(appEvents.list.table.getCell(1, 0).getText()).toBe(`person\n${currentUser}`); - // Update (route) - expect(appEvents.list.table.getCell(2, 1).getText()).toBe('audit\napp\nupdate'); - expect(appEvents.list.table.getCell(2, 0).getText()).toBe(`person\n${currentUser}`); - }); + const checkEventTableItem = (data: { [columnHeader: string]: string }[], text) => { + const item = data.find(i => i.type === text); + expect(item).toBeDefined(); + expect(item.actor).toBe(`person\n${currentUser}`); + }; + + // Don't worry about order of events + appEvents.list.table.getTableData().then(data => { + // Create + checkEventTableItem(data, 'audit\napp\ncreate'); + // Lifecycle - buildpack(s) + checkEventTableItem(data, 'audit\napp\nupdate'); + // Map Route + checkEventTableItem(data, 'audit\napp\nmap-route'); + // Upload bits + checkEventTableItem(data, 'audit\napp\nupload-bits'); + // Build Create + checkEventTableItem(data, 'audit\napp\nbuild\ncreate'); + }); + }); }); describe('Instance scaling', () => { diff --git a/src/test-e2e/application/application-deploy-local-e2e.spec.ts b/src/test-e2e/application/application-deploy-local-e2e.spec.ts index a97e018915..463e0b71cf 100644 --- a/src/test-e2e/application/application-deploy-local-e2e.spec.ts +++ b/src/test-e2e/application/application-deploy-local-e2e.spec.ts @@ -22,7 +22,7 @@ const spaceName = e2e.secrets.getDefaultCFEndpoint().testSpace; let applicationZipFile; -describe('Application Deploy - ', function () { +describe('Application Deploy - ', () => { const testAppName = ApplicationE2eHelper.createApplicationName(); const appDetails = { cfGuid: '', @@ -51,12 +51,12 @@ describe('Application Deploy - ', function () { beforeAll(() => nav.goto(SideNavMenuItem.Applications)); // Might take a bit longer to deploy the app than the global default timeout allows - beforeEach(function () { + beforeEach(() => { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; jasmine.DEFAULT_TIMEOUT_INTERVAL = newTimeout; }); - afterEach(function () { + afterEach(() => { jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; });