1
+ import json
1
2
from typing import Optional
2
3
3
- from primehub import Helpful , cmd , Module
4
+ from primehub import Helpful , cmd , Module , primehub_load_config
5
+ from primehub .utils import PrimeHubException
6
+ from primehub .utils .optionals import file_flag
4
7
from primehub .resource_operations import GroupResourceOperation
8
+ from primehub .utils .validator import validate_name
5
9
6
10
7
11
class Images (Helpful , Module , GroupResourceOperation ):
@@ -37,7 +41,7 @@ def list(self) -> list:
37
41
"""
38
42
return self .do_list (Images .query , Images .resource_name )
39
43
40
- @cmd (name = 'get' , description = 'Get a image by name' , return_required = True )
44
+ @cmd (name = 'get' , description = 'Get an image by name' , return_required = True )
41
45
def get (self , name ) -> Optional [dict ]:
42
46
"""
43
47
Get an image from the current group
@@ -50,5 +54,103 @@ def get(self, name) -> Optional[dict]:
50
54
"""
51
55
return self .do_get (Images .query , Images .resource_name , name )
52
56
57
+ @cmd (name = 'create' , description = 'Create an image' , optionals = [('file' , file_flag )])
58
+ def _create_cmd (self , ** kwargs ):
59
+ """
60
+ Create an image for the current group
61
+
62
+ :type file: str
63
+ :param file: The file path of the configurations
64
+
65
+ :rtype dict
66
+ :return The image
67
+ """
68
+ config = primehub_load_config (filename = kwargs .get ('file' , None ))
69
+ if not config :
70
+ invalid_config ('The configuration is required.' )
71
+
72
+ return self .create (config )
73
+
74
+ def create (self , config ):
75
+ """
76
+ Create an image for the current group
77
+
78
+ :type config: dict
79
+ :param config: The configurations for creating an image
80
+
81
+ :rtype dict
82
+ :return The image
83
+ """
84
+ payload = validate (config )
85
+ payload ['groups' ] = {'connect' : [{'id' : self .group_id }]}
86
+ payload ['groupName' ] = self .group_name
87
+
88
+ query = """
89
+ mutation CreateImageMutation($data: ImageCreateInput!) {
90
+ createImage(data: $data) {
91
+ id
92
+ }
93
+ }
94
+ """
95
+
96
+ results = self .request ({'data' : payload }, query )
97
+ if 'data' not in results :
98
+ return results
99
+ return results ['data' ]['createImage' ]
100
+
101
+ @cmd (name = 'delete' , description = 'Delete an image by name' , return_required = True )
102
+ def delete (self , name ):
103
+ """
104
+ Delete an image by id
105
+
106
+ :type id: str
107
+ :param id: the id of an image
108
+
109
+ :rtype dict
110
+ :return an image
111
+ """
112
+
113
+ query = """
114
+ mutation DeleteImageMutation($where: ImageWhereUniqueInput!) {
115
+ deleteImage(where: $where) {
116
+ id
117
+ }
118
+ }
119
+ """
120
+ self .get (name )
121
+
122
+ results = self .request ({'where' : {'id' : name }}, query )
123
+ if 'data' not in results :
124
+ return results
125
+ return results ['data' ]['deleteImage' ]
126
+
53
127
def help_description (self ):
54
128
return "Get a image or list images"
129
+
130
+
131
+ def validate (payload : dict , for_update = False ):
132
+ if not for_update :
133
+ validate_name (payload )
134
+
135
+ image_type = payload .get ('type' )
136
+ if image_type is not None and image_type not in ['cpu' , 'gpu' , 'both' ]:
137
+ raise PrimeHubException ("type should be one of ['cpu', 'gpu', 'both']" )
138
+ url = payload .get ('url' )
139
+ if url is None :
140
+ raise PrimeHubException ("url is required" )
141
+
142
+ return payload
143
+
144
+
145
+ def invalid_config (message : str ):
146
+ example = """
147
+ {
148
+ "name": "base",
149
+ "displayName": "Base image",
150
+ "description": "base-notebook with python 3.7",
151
+ "type": "both",
152
+ "url": "infuseai/docker-stacks:base-notebook-63fdf50a",
153
+ "urlForGpu": "infuseai/docker-stacks:base-notebook-63fdf50a-gpu"
154
+ }
155
+ """ .strip ()
156
+ raise PrimeHubException (message + "\n \n Example:\n " + json .dumps (json .loads (example ), indent = 2 ))
0 commit comments