@@ -40,7 +40,6 @@ import {
40
40
Workspace ,
41
41
WorkspaceContext ,
42
42
WorkspaceCreationResult ,
43
- WorkspaceImageBuild ,
44
43
WorkspaceInfo ,
45
44
WorkspaceInstance ,
46
45
WorkspaceInstancePort ,
@@ -120,7 +119,6 @@ import { ContextParser } from "./context-parser-service";
120
119
import { GitTokenScopeGuesser } from "./git-token-scope-guesser" ;
121
120
import { isClusterMaintenanceError } from "./workspace-starter" ;
122
121
import { HeadlessLogUrls } from "@gitpod/gitpod-protocol/lib/headless-workspace-log" ;
123
- import { HeadlessLogService , HeadlessLogEndpoint } from "./headless-log-service" ;
124
122
import { ConfigProvider , InvalidGitpodYMLError } from "./config-provider" ;
125
123
import { ProjectsService } from "../projects/projects-service" ;
126
124
import { IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol" ;
@@ -140,7 +138,6 @@ import {
140
138
UserFeatureSettings ,
141
139
WorkspaceTimeoutSetting ,
142
140
} from "@gitpod/gitpod-protocol/lib/protocol" ;
143
- import { Deferred } from "@gitpod/gitpod-protocol/lib/util/deferred" ;
144
141
import { ListUsageRequest , ListUsageResponse } from "@gitpod/gitpod-protocol/lib/usage" ;
145
142
import { VerificationService } from "../auth/verification-service" ;
146
143
import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-mode" ;
@@ -235,8 +232,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
235
232
236
233
@inject ( GitTokenScopeGuesser ) private readonly gitTokenScopeGuesser : GitTokenScopeGuesser ,
237
234
238
- @inject ( HeadlessLogService ) private readonly headlessLogService : HeadlessLogService ,
239
-
240
235
@inject ( ProjectsService ) private readonly projectsService : ProjectsService ,
241
236
242
237
@inject ( IDEService ) private readonly ideService : IDEService ,
@@ -1866,6 +1861,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1866
1861
return ;
1867
1862
}
1868
1863
1864
+ // TODO(gpl) Remove entirely after FGA rollout
1869
1865
const logCtx : LogContext = { userId : user . id , workspaceId } ;
1870
1866
// eslint-disable-next-line prefer-const
1871
1867
let { instance, workspace } = await this . internGetCurrentWorkspaceInstance ( ctx , user , workspaceId ) ;
@@ -1877,103 +1873,18 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
1877
1873
const teamMembers = await this . organizationService . listMembers ( user . id , workspace . organizationId ) ;
1878
1874
await this . guardAccess ( { kind : "workspaceLog" , subject : workspace , teamMembers } , "get" ) ;
1879
1875
1880
- // wait for up to 20s for imageBuildLogInfo to appear due to:
1881
- // - db-sync round-trip times
1882
- // - but also: wait until the image build actually started (image pull!), and log info is available!
1883
- for ( let i = 0 ; i < 10 ; i ++ ) {
1884
- if ( instance . imageBuildInfo ?. log ) {
1885
- break ;
1886
- }
1887
- await new Promise ( ( resolve ) => setTimeout ( resolve , 2000 ) ) ;
1888
-
1889
- const wsi = await this . workspaceDb . trace ( ctx ) . findInstanceById ( instance . id ) ;
1890
- if ( ! wsi || ! [ "preparing" , "building" ] . includes ( wsi . status . phase ) ) {
1891
- log . debug ( logCtx , `imagebuild logs: instance is not/no longer in 'building' state` , {
1892
- phase : wsi ?. status . phase ,
1893
- } ) ;
1894
- return ;
1895
- }
1896
- instance = wsi as WorkspaceInstance ; // help the compiler a bit
1897
- }
1898
-
1899
- const logInfo = instance . imageBuildInfo ?. log ;
1900
- if ( ! logInfo ) {
1901
- log . error ( logCtx , "cannot watch imagebuild logs for workspaceId: no image build info available" ) ;
1902
- throw new ApplicationError (
1903
- ErrorCodes . HEADLESS_LOG_NOT_YET_AVAILABLE ,
1904
- "cannot watch imagebuild logs for workspaceId" ,
1905
- ) ;
1906
- }
1907
-
1908
- const aborted = new Deferred < boolean > ( ) ;
1909
- try {
1910
- const logEndpoint : HeadlessLogEndpoint = {
1911
- url : logInfo . url ,
1912
- headers : logInfo . headers ,
1913
- } ;
1914
- let lineCount = 0 ;
1915
- await this . headlessLogService . streamImageBuildLog (
1916
- logCtx ,
1917
- logEndpoint ,
1918
- async ( chunk ) => {
1919
- if ( aborted . isResolved ) {
1920
- return ;
1921
- }
1922
-
1923
- try {
1924
- chunk = chunk . replace ( "\n" , WorkspaceImageBuild . LogLine . DELIMITER ) ;
1925
- lineCount += chunk . split ( WorkspaceImageBuild . LogLine . DELIMITER_REGEX ) . length ;
1926
-
1927
- client . onWorkspaceImageBuildLogs ( undefined as any , {
1928
- text : chunk ,
1929
- isDiff : true ,
1930
- upToLine : lineCount ,
1931
- } ) ;
1932
- } catch ( err ) {
1933
- log . error ( "error while streaming imagebuild logs" , err ) ;
1934
- aborted . resolve ( true ) ;
1935
- }
1936
- } ,
1937
- aborted ,
1938
- ) ;
1939
- } catch ( err ) {
1940
- // This error is most likely a temporary one (too early). We defer to the client whether they want to keep on trying or not.
1941
- log . debug ( logCtx , "cannot watch imagebuild logs for workspaceId" , err ) ;
1942
- throw new ApplicationError (
1943
- ErrorCodes . HEADLESS_LOG_NOT_YET_AVAILABLE ,
1944
- "cannot watch imagebuild logs for workspaceId" ,
1945
- ) ;
1946
- } finally {
1947
- aborted . resolve ( false ) ;
1948
- }
1876
+ await this . workspaceService . watchWorkspaceImageBuildLogs ( user . id , workspaceId , client ) ;
1949
1877
}
1950
1878
1951
1879
async getHeadlessLog ( ctx : TraceContext , instanceId : string ) : Promise < HeadlessLogUrls > {
1952
1880
traceAPIParams ( ctx , { instanceId } ) ;
1953
1881
1954
1882
const user = await this . checkAndBlockUser ( "getHeadlessLog" , { instanceId } ) ;
1955
- const logCtx : LogContext = { instanceId } ;
1956
-
1957
- const ws = await this . workspaceDb . trace ( ctx ) . findByInstanceId ( instanceId ) ;
1958
- if ( ! ws ) {
1959
- throw new ApplicationError ( ErrorCodes . NOT_FOUND , `Workspace ${ instanceId } not found` ) ;
1960
- }
1961
1883
1962
- const wsiPromise = this . workspaceDb . trace ( ctx ) . findInstanceById ( instanceId ) ;
1963
- const teamMembers = await this . organizationService . listMembers ( user . id , ws . organizationId ) ;
1964
-
1965
- await this . guardAccess ( { kind : "workspaceLog" , subject : ws , teamMembers } , "get" ) ;
1966
-
1967
- const wsi = await wsiPromise ;
1968
- if ( ! wsi ) {
1969
- throw new ApplicationError ( ErrorCodes . NOT_FOUND , `Workspace instance for ${ instanceId } not found` ) ;
1970
- }
1971
-
1972
- const urls = await this . headlessLogService . getHeadlessLogURLs ( logCtx , wsi , ws . ownerId ) ;
1973
- if ( ! urls || ( typeof urls . streams === "object" && Object . keys ( urls . streams ) . length === 0 ) ) {
1974
- throw new ApplicationError ( ErrorCodes . NOT_FOUND , `Headless logs for ${ instanceId } not found` ) ;
1975
- }
1976
- return urls ;
1884
+ return this . workspaceService . getHeadlessLog ( user . id , instanceId , async ( workspace ) => {
1885
+ const teamMembers = await this . organizationService . listMembers ( user . id , workspace . organizationId ) ;
1886
+ await this . guardAccess ( { kind : "workspaceLog" , subject : workspace , teamMembers } , "get" ) ;
1887
+ } ) ;
1977
1888
}
1978
1889
1979
1890
private async internGetCurrentWorkspaceInstance (
0 commit comments