Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from datasette import hookimpl 

2import click 

3import json 

4import os 

5import re 

6from subprocess import check_call, check_output 

7 

8from .common import ( 

9 add_common_publish_arguments_and_options, 

10 fail_if_publish_binary_not_installed, 

11) 

12from ..utils import temporary_docker_directory 

13 

14 

15@hookimpl 

16def publish_subcommand(publish): 

17 @publish.command() 

18 @add_common_publish_arguments_and_options 

19 @click.option( 

20 "-n", 

21 "--name", 

22 default="datasette", 

23 help="Application name to use when building", 

24 ) 

25 @click.option( 

26 "--service", default="", help="Cloud Run service to deploy (or over-write)" 

27 ) 

28 @click.option("--spatialite", is_flag=True, help="Enable SpatialLite extension") 

29 @click.option( 

30 "--show-files", 

31 is_flag=True, 

32 help="Output the generated Dockerfile and metadata.json", 

33 ) 

34 @click.option( 

35 "--memory", 

36 callback=_validate_memory, 

37 help="Memory to allocate in Cloud Run, e.g. 1Gi", 

38 ) 

39 def cloudrun( 

40 files, 

41 metadata, 

42 extra_options, 

43 branch, 

44 template_dir, 

45 plugins_dir, 

46 static, 

47 install, 

48 plugin_secret, 

49 version_note, 

50 secret, 

51 title, 

52 license, 

53 license_url, 

54 source, 

55 source_url, 

56 about, 

57 about_url, 

58 name, 

59 service, 

60 spatialite, 

61 show_files, 

62 memory, 

63 ): 

64 fail_if_publish_binary_not_installed( 

65 "gcloud", "Google Cloud", "https://cloud.google.com/sdk/" 

66 ) 

67 project = check_output( 

68 "gcloud config get-value project", shell=True, universal_newlines=True 

69 ).strip() 

70 

71 if not service: 

72 # Show the user their current services, then prompt for one 

73 click.echo("Please provide a service name for this deployment\n") 

74 click.echo("Using an existing service name will over-write it") 

75 click.echo("") 

76 existing_services = get_existing_services() 

77 if existing_services: 

78 click.echo("Your existing services:\n") 

79 for existing_service in existing_services: 

80 click.echo( 

81 " {name} - created {created} - {url}".format( 

82 **existing_service 

83 ) 

84 ) 

85 click.echo("") 

86 service = click.prompt("Service name", type=str) 

87 

88 extra_metadata = { 

89 "title": title, 

90 "license": license, 

91 "license_url": license_url, 

92 "source": source, 

93 "source_url": source_url, 

94 "about": about, 

95 "about_url": about_url, 

96 } 

97 

98 environment_variables = {} 

99 if plugin_secret: 

100 extra_metadata["plugins"] = {} 

101 for plugin_name, plugin_setting, setting_value in plugin_secret: 

102 environment_variable = ( 

103 "{}_{}".format(plugin_name, plugin_setting) 

104 .upper() 

105 .replace("-", "_") 

106 ) 

107 environment_variables[environment_variable] = setting_value 

108 extra_metadata["plugins"].setdefault(plugin_name, {})[ 

109 plugin_setting 

110 ] = {"$env": environment_variable} 

111 

112 with temporary_docker_directory( 

113 files, 

114 name, 

115 metadata, 

116 extra_options, 

117 branch, 

118 template_dir, 

119 plugins_dir, 

120 static, 

121 install, 

122 spatialite, 

123 version_note, 

124 secret, 

125 extra_metadata, 

126 environment_variables, 

127 ): 

128 if show_files: 

129 if os.path.exists("metadata.json"): 

130 print("=== metadata.json ===\n") 

131 print(open("metadata.json").read()) 

132 print("\n==== Dockerfile ====\n") 

133 print(open("Dockerfile").read()) 

134 print("\n====================\n") 

135 

136 image_id = "gcr.io/{project}/{name}".format(project=project, name=name) 

137 check_call("gcloud builds submit --tag {}".format(image_id), shell=True) 

138 check_call( 

139 "gcloud run deploy --allow-unauthenticated --platform=managed --image {} {}{}".format( 

140 image_id, service, " --memory {}".format(memory) if memory else "" 

141 ), 

142 shell=True, 

143 ) 

144 

145 

146def get_existing_services(): 

147 services = json.loads( 

148 check_output( 

149 "gcloud run services list --platform=managed --format json", 

150 shell=True, 

151 universal_newlines=True, 

152 ) 

153 ) 

154 return [ 

155 { 

156 "name": service["metadata"]["name"], 

157 "created": service["metadata"]["creationTimestamp"], 

158 "url": service["status"]["address"]["url"], 

159 } 

160 for service in services 

161 ] 

162 

163 

164def _validate_memory(ctx, param, value): 

165 if value and re.match(r"^\d+(Gi|G|Mi|M)$", value) is None: 

166 raise click.BadParameter("--memory should be a number then Gi/G/Mi/M e.g 1Gi") 

167 return value