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