-
Notifications
You must be signed in to change notification settings - Fork 9
/
migrateGEEAssets.py
196 lines (172 loc) · 7.55 KB
/
migrateGEEAssets.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
import ee, os, json, re
ee.Initialize()
###################################################################################################
"""
This script recursively migrates Google Earth Engine assets from one repository to a new one, sets permissions, and deletes old assets if needed.
**Important** for this to work you need the following:
- The credential you're using must have editor permissions in both the source and destination repositories
OR
- The credential you're using must have editor permissions in the destination repository, and you are willing to
change the permissions of all the original assets to "Anyone Can Read" (to do this, set changePermissions = True below)
- The geeViz package installed in your python instance. (https://github.com/gee-community/geeViz)
"""
# Written by:
# Ian Housman [email protected] [email protected]
# Leah Campbell [email protected] [email protected]
# RedCastle Resources Inc.
# MIT License
###################################################################################################
# Repository you are moving from:
sourceRoot = "users/iwhousman/test"
# sourceRoot = 'projects/USFS/LCMS-NFS/R1/FNF'
# sourceRoot = 'projects/lcms-292214/assets/AK-Ancillary-Data'
# Repository you are moving to:
# It is assumed this folder already exists and user account has write access to it
# destinationRoot = 'projects/lcms-292214/assets/migrationTest/FNF'
# destinationRoot = 'users/usfs-ihousman/migrationTest'
# If the credential you're using does not have editor permissions in the source repository
# Must include 'user:' prefix if it is a individual's Email or 'group:' if it is a Google Group
changeSourcePermissions = True
sourceReaders = []
sourceWriters = ["user:[email protected]"]
source_all_users_can_read = False
changeDestinationPermissions = True
destinationReaders = []
destinationWriters = []
destination_all_users_can_read = False
###################################################################################################
# Function to get all folders, imageCollections, images, and tables under a given folder or imageCollection level
def getTree(fromRoot, toRoot, treeList=[]):
pathPrefix = "projects/earthengine-legacy/assets/"
# Clean up the given paths
if fromRoot[-1] != "/":
fromRoot += "/"
if toRoot[-1] != "/":
toRoot += "/"
# Handle inconsistencies with the earthengine-legacy prefix
if re.match("^projects/[^/]+/assets/.*$", fromRoot) == None:
fromRoot = pathPrefix + fromRoot
if re.match("^projects/[^/]+/assets/.*$", toRoot) == None:
toRoot = pathPrefix + toRoot
# print(fromRoot,toRoot)
# List assets
try:
assets = ee.data.listAssets({"parent": fromRoot})["assets"]
except Exception as e1:
print(e1)
# try:
# assets = ee.data.listAssets({'parent':fromRoot})['assets']
# except Exception as e2:
# print(e2)
# Reursively walk down the tree
nextLevels = []
for asset in assets:
fromID = asset["name"]
fromType = asset["type"]
# fromID = fromID.replace('projects/earthengine-legacy/assets/','')
toID = fromID.replace(fromRoot, toRoot)
if fromType in ["FOLDER", "IMAGE_COLLECTION"]:
nextLevels.append([fromID, toID])
treeList.append([fromType, fromID, toID])
for i1, i2 in nextLevels:
getTree(i1, i2, treeList)
return treeList
###################################################################################################
# Function for setting permissions for all files under a specified root level
# Either a list of assets a root to start from can be provided
def batchChangePermissions(
assetList=None, root=None, readers=[], writers=[], all_users_can_read=False
):
if assetList == None:
assetList = [i[1] for i in getTree(root, root)]
for assetID in assetList:
print("Changing permissions for: {}".format(assetID))
try:
ee.data.setAssetAcl(
assetID,
json.dumps(
{
"writers": writers,
"all_users_can_read": all_users_can_read,
"readers": readers,
}
),
)
except Exception as e:
print(e)
###################################################################################################
# Function to copy all folders, imageCollections, images, and tables under a given folder or imageCollection level
# Permissions can also be set here
def copyAssetTree(
fromRoot,
toRoot,
changePermissions=False,
readers=[],
writers=[],
all_users_can_read=False,
):
treeList = getTree(fromRoot, toRoot)
# Iterate across all assets and copy and create when appropriate
for fromType, fromID, toID in treeList:
if fromType in ["FOLDER", "IMAGE_COLLECTION"]:
try:
print("Creating {}: {}".format(fromType, toID))
ee.data.createAsset({"type": "Image_Collection", "name": toID})
except Exception as e:
print(e)
else:
try:
print("Copying {}: {}".format(fromType, toID))
ee.data.copyAsset(fromID, toID, False)
except Exception as e:
print(e)
print()
print()
if changePermissions:
batchChangePermissions(
assetList=[i[2] for i in treeList],
root=None,
readers=[],
writers=[],
all_users_can_read=False,
)
###################################################################################################
# Function to delete all folders, imageCollections, images, and tables under a given folder or imageCollection level
def deleteAssetTree(root):
answer = input(
"Are you sure you want to delete all assets under {}? (y = yes, n = no) ".format(
root
)
)
print(answer)
if answer.lower() == "y":
answer = input(
"You answered yes. Just double checking. Are you sure you want to delete all assets under {}? (y = yes, n = no) ".format(
root
)
)
if answer.lower() == "y":
treeList = getTree(root, root)
treeList.reverse()
for fromType, ID1, ID2 in treeList:
print("Deleting {}".format(ID1))
try:
ee.data.deleteAsset(ID1)
except Exception as e:
print(e)
###################################################################################################
# Step 1: Make sure source has account added as reader (may need to use different credentials for this)
batchChangePermissions(
None, sourceRoot, sourceReaders, sourceWriters, source_all_users_can_read
)
###################################################################################################
# Step 2: Use this function to copy assets
# copyAssetTree(sourceRoot,destinationRoot,changeDestinationPermissions,destinationReaders,destinationWriters,destination_all_users_can_read)
###################################################################################################
#!!!!!!! DANGER !!!!!!!!!
#!!!!!!! DANGER !!!!!!!!!
#!!!!!!! DANGER !!!!!!!!!
#!!!!!!! DANGER !!!!!!!!!
# Optional Step 3: Once all assets are copied and inspected, you can use this method to delete all files under the root level
# This method is final and there is no way to undo this
# deleteAssetTree(destinationRoot)