Kiln » KilnSupportScripts Powershell Scripts to help monitor a Kiln environment. Contact Fog Creek support before using.
Clone URL:  
Pushed to one repository · View In Graph Contained in tip

merge

Changeset 3e61a62ffd2c

Parents bb959c445c8a

Parents 57dcd44b2fb2

by Profile picture of Developer Wiki Admin AccountDeveloper Wiki Admin Account

Changes to 3 files · Browse files at 3e61a62ffd2c Showing diff from parent bb959c445c8a 57dcd44b2fb2 Diff from another changeset...

 
69
70
71
72
73
74
 
 
 
75
76
77
 
97
98
99
100
 
101
102
103
 
303
304
305
306
307
308
309
 
69
70
71
 
 
 
72
73
74
75
76
77
 
97
98
99
 
100
101
102
103
 
303
304
305
 
306
307
308
@@ -69,9 +69,9 @@
  The name of the IIS Website that FogBugz and Kiln are running under. If you provide this,   the script will attempt to restart IIS if it cannot load the Kiln web page.   -.PARAMETER noRestart - A flag which when set will force the script to only send alert messages and not - attempt to restart any services automatically. +.PARAMETER tryAutoRestart + A flag which when set will modify the behavior of the script to attempt to restart services + which it detects are not running or to reenqueue tasks when too many are found.    .PARAMETER reenqueuePath   The path to the Reenqueue script, this is used to try to resuscitate the Queue when problems are detected. @@ -97,7 +97,7 @@
  [string]$esUrl = "http://localhost:9200/",   [string]$queueStatsUrl = "http://localhost:56785/stats.json",   [string]$iisSiteName = "", - [switch]$noRestart, + [switch]$tryAutoRestart,   [string]$reenqueuePath = ".\reenqueue_2.9_tasks.ps1"   )   @@ -303,7 +303,6 @@
      -$tryAutoRestart = !($noRestart) # Needed a negative name for the parameter since the default is true. Sanity rename here.  $kssNeedsRestart = $false  $kqsNeedsRestart = $false  $iisNeedsRestart = $false
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
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
 ################################  #  # This script will migrate repositories from one Kiln Server to another. It should work as long as  # there are no name clashes between the old server and the new one, but it has only be tested with a  # completely empty new server.  #  # The script should be run on a machine which has sufficient disk space to clone copies of ALL of the  # repositories from the old kiln server. This means it also requires that Mercurial be installed in order to run. - +# +# Beware: Branches will not migrate properly if the parent repo has been changed since the original point of the branch!              import sys  import os  import urllib  import urllib2  import urlparse  from Queue import Queue  try:   import json  except ImportError:   import simplejson as json        # Set debug to 0 for errors only, 1 for basic output, 2 for verbose output  debug = 1  sourceServer = 'https://my.kilnhg.com'  sourceToken = 'SECRET'  destinationServer = 'http://server/fogbugz/kiln'  destinationToken = 'SECRET'        def debug_print(message, level=1):   if ( debug >= level ):   print message          # We cycle through the heirarchy of objects and push them over to the new server.  # Projects contain Groups, which in turn contain Repositories, so we have a nested loop in that order.  # Note that this does NOT transfer the Users from the previous server nor any specific  # permissions on the Projects/Groups/Repositories.      # Create a dictionary from old ixRepos to new ones.  # oldIxRepo = 123  # newIxRepo = 456  # repo_map[123] = 456  repo_map = {}    # A list of pairs indicating the parent associations we will have to recreate. (old_ixrepo, old_parent_ixrepo)  old_parent_associations = []    # Load all the source projects  src_projects = json.load(urllib2.urlopen('%s/Api/1.0/project/?token=%s' % (sourceServer, sourceToken)))    ###### PROJECT LEVEL LOOP ######  for src_project in src_projects:   debug_print("Working on project '%s'" % (src_project['sName']))   debug_print("SOURCE PROJECT DATA:\n"+str(src_project), 2)     dest_project = None   # Try to find the project on the Destination Server   dest_projects = json.load(urllib2.urlopen('%s/Api/1.0/Project?token=%s' % (destinationServer, destinationToken)))   for a_dest_project in dest_projects:   if (a_dest_project['sName'] == src_project['sName']):   dest_project = json.load(urllib2.urlopen('%s/Api/1.0/Project/%s?token=%s' % (destinationServer, a_dest_project['ixProject'], destinationToken)))   debug_print(" - Found an existing match on the destination server. ixProject = %s" % (dest_project['ixProject']))   debug_print(" - DESTINATION PROJECT DATA:\n" + str(dest_project), 2)     # If we don't find an existing project, then create a new project with the information we grabbed from the old server   if (not dest_project):   data = urllib.urlencode({'token': destinationToken, 'sName': src_project['sName'], \   'sDescription': src_project['sDescription'], 'permissionDefault': src_project['permissionDefault']})   dest_project = json.load(urllib2.urlopen('%s/Api/1.0/Project/Create' % (destinationServer), data))   debug_print(" + Created a new Project on the destination server. ixProject = %s" % (dest_project['ixProject']))   debug_print(" + DESTINATION PROJECT DATA:\n" + str(dest_project), 2)       ###### REPOSITORY GROUP LEVEL LOOP ######   for src_repo_group in src_project['repoGroups']:   debug_print(" Working on Group '%s'" % (src_repo_group['sName']))   debug_print(" SOURCE REPO GROUP DATA:\n" + str(src_repo_group), 2)       dest_repo_group = None   # Try to find the project on the Destination Server   dest_repo_groups = dest_project['repoGroups']   for a_dest_repo_group in dest_repo_groups:   if (a_dest_repo_group['sName'] == src_repo_group['sName']):   dest_repo_group = json.load(urllib2.urlopen('%s/Api/1.0/RepoGroup/%s?token=%s' % (destinationServer, a_dest_repo_group['ixRepoGroup'], destinationToken)))   debug_print(" - Found an existing match on the destination server. ixRepogroup = %s" % (dest_repo_group['ixRepoGroup']))   debug_print(" - DESTINATION REPO GROUP DATA:\n" + str(dest_repo_group), 2)       # If we don't find an existing project, then create a new project with the information we grabbed from the old server   if (not dest_repo_group):   data = urllib.urlencode({'token': destinationToken, 'sName': src_repo_group['sName'], 'ixProject': dest_project['ixProject']})   dest_repo_group = json.load(urllib2.urlopen('%s/Api/1.0/RepoGroup/Create/' % (destinationServer), data))   debug_print(" + Created a new Repository Group on the destination server. ixRepoGroup = %s" % (dest_repo_group['ixRepoGroup']))   debug_print(" + DESTINATION REPO GROUP DATA:\n" + str(dest_repo_group), 2)         # We build a queue of the repositories so that we can easily wait to process any repos that need parents created first   q = Queue()   for src_repo in src_repo_group['repos']:   q.put(src_repo)       ###### REPOSITORY LEVEL LOOP ######   while (not q.empty()):   src_repo = q.get()     # If the repo has a parent that has NOT been created in the destination yet, then re-enqueue it for later   if ((src_repo['ixParent']) and not (src_repo['ixParent'] in repo_map)):   q.put(src_repo)   debug_print(" Postponing work on Repository '%s'" % (src_repo['sName']))   continue     debug_print(" Working on Repository '%s'" % (src_repo['sName']))     # If the old repository had a parent, add the assocation to the old_parent_associations list   #if src_repo['ixParent']:   # old_parent_associations += [(src_repo['ixRepo'], src_repo['ixParent'])] # add (old_ixrepo, old_parent_ixrepo) to the list       dest_repo = None   # Try to find the project on the Destination Server   dest_repos = dest_repo_group['repos']   for a_dest_repo in dest_repos:   if (a_dest_repo['sName'] == src_repo['sName']):   dest_repo = json.load(urllib2.urlopen('%s/Api/1.0/Repo/%s?token=%s' % (destinationServer, a_dest_repo['ixRepo'], destinationToken)))   debug_print(" - Found an existing match on the destination server. ixRepo = %s" % (dest_repo['ixRepo']))   debug_print(" - DESTINATION REPOSITORY DATA:\n" + str(dest_repo), 2)     # If we don't find an existing repo, then create a new repo with the information we grabbed from the old server   if (not dest_repo):   if (src_repo['ixParent']): + # By setting the ixParent field, when Repo/Create is called, it will create a new branch from the ixParent Repo. + # This means, that the point at which the src repo branched off from the parent can and most likely will be different from the + # point at which the dest repo gets branched. (One option I know of to fix this, after the fact, is to strip changesets in + # the dest repo back to the point where the branch was created in the src repo. Then push the src repo to the dest repo and + # the src and dest branches should be back in sync. + debug_print(" !!! Warning: Branches may not migrate properly !!!")   data = urllib.urlencode({'token': destinationToken,   'sName': src_repo['sName'],   'sDescription': src_repo['sDescription'],   'ixRepoGroup': dest_repo_group['ixRepoGroup'],   'permissionDefault': src_repo['permissionDefault'],   'ixParent': repo_map[src_repo['ixParent']],   'fCentral': 'false'   })   else:   data = urllib.urlencode({'token': destinationToken,   'sName': src_repo['sName'],   'sDescription': src_repo['sDescription'],   'ixRepoGroup': dest_repo_group['ixRepoGroup'],   'permissionDefault': src_repo['permissionDefault']   })   dest_repo = json.load(urllib2.urlopen('%s/Api/1.0/Repo/Create/' % (destinationServer), data))   debug_print(" + Created a new Repository on the destination server. ixRepo = %s" % (dest_repo['ixRepo']))   debug_print(" + DESTINATION REPOSITORY DATA:\n" + str(dest_repo), 2)       # Record the mapping from the old server to the new server. repo_map[oldIxRepo] = newIxRepo   repo_map[src_repo['ixRepo']] = dest_repo['ixRepo']       # Build a unique folder name to clone the repo into   folder_name = src_repo['sName'] + "-"+str(src_repo['ixRepo'])     # Convert empty RepoGroup slug values to the default 'Group'   group_name = src_repo_group['sSlug']   if (group_name == ''):   group_name = 'Group'   new_group_name = dest_repo_group['sSlug']   if (new_group_name == ''):   new_group_name = 'Group'     # Clone the repo locally, and then push it to the destination server   os.system("hg clone " + sourceServer +'/Code/'+ src_project["sSlug"] +'/'+ group_name +'/'+ src_repo["sSlug"] +' "'+ folder_name + '"')   os.chdir(folder_name)   os.system("hg push " + destinationServer +'/Code/'+ dest_project["sSlug"] +'/'+ new_group_name +'/'+ dest_repo["sSlug"])   os.chdir('..')        debug_print("\nDONE!")
Change 1 of 1 Show Entire File misc/​repair_all_repos.ps1 Stacked
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
@@ -0,0 +1,117 @@
+<# +.SYNOPSIS + Repairs all repositories on a Kiln server + +.DESCRIPTION + Uses the Kiln API to gather information about all repositories hosted on the Kiln server and then + issues API commands to repair each of the repositories. + +.EXAMPLE + .\repair_all_repos.ps1 -kilnUrl "http://my.fogbugz/kiln" -token "gfd4567f2g7d8f2g4d6f8sdsdg88" + +.PARAMETER kilnUrl + Where Kiln is hosted, this URL must be reachable from the local machine + +.PARAMETER token + A valid API token for the Kiln server + +.NOTES + Author: Quentin Schroeder + Version: 1.0 + Date: Jan 22, 2013 +#> + + +param([string]$kilnUrl = "http://localhost/kiln", + [string]$token = "" + ) + + +function main() { + if ($token -eq "") {write-host "Must provide a token to authorize access to Kiln."; exit;} + + $url = "{0}/Api/1.0/Project?token={1}" -f ($kilnUrl, $token) + write-host ("Getting repo information from {0}" -f $url) + $response = (New-Object System.Net.WebClient).DownloadString($url) + if (!($?)) {write-host "Failed to get repo information. Confirm the kilnUrl parameter is correct."; exit;} + + $responseXml = Convert-JsonToXml($response) + $projects = $responseXml.root.childnodes + + foreach ($project in $projects) { + foreach ($group in $project.repoGroups.childnodes) { + foreach ($repo in $group.repos.childnodes) { + $ixRepo = $repo.ixRepo."#text" + $repoName = $repo.sName."#text" + $URI = "{0}/api/1.0/repo/{1}/repair?token={2}" -f ($kilnUrl, $ixRepo, $token) + write-host ("Attempting to repair repo '{0}' (ixRepo: {1})" -f ($repoName, $ixRepo) ) + Execute-HTTPPostCommand $URI "a=1" + if (!($?)) {write-host "Failed!!"} + } + } + } +} + + + +# This is provided as an alternative to ConvertFrom-JSON, which requires Powershell V3 +# which is not on most servers by default and requires a reboot to install. +# Source: (https://www.cogmotive.com/blog/powershell/parsing-json-in-powershell-xml-the-member-item-is-already-present) +Add-Type -Assembly System.ServiceModel.Web,System.Runtime.Serialization +function Convert-JsonToXml([string]$json) +{ + $bytes = [byte[]][char[]]$json + $quotas = [System.Xml.XmlDictionaryReaderQuotas]::Max + $jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($bytes,$quotas) + try + { + $xml = new-object System.Xml.XmlDocument + $xml.Load($jsonReader) + $xml + } + finally + { + $jsonReader.Close() + } +} + + + +# Source: (http://stackoverflow.com/questions/5246836/user-powershell-script-to-post-to-url) +function Execute-HTTPPostCommand() { + param( + [string] $target = $null, + [string] $post = $null + ) + + $webRequest = [System.Net.WebRequest]::Create($target) + $webRequest.ContentType = "text/html" + $PostStr = [System.Text.Encoding]::UTF8.GetBytes($post) + $webrequest.ContentLength = $PostStr.Length + $webRequest.ServicePoint.Expect100Continue = $false + $webRequest.Method = "POST" + + $requestStream = $webRequest.GetRequestStream() + $requestStream.Write($PostStr, 0,$PostStr.length) + $requestStream.Close() + + try + { + [System.Net.WebResponse] $resp = $webRequest.GetResponse() + } + catch [Net.WebException] + { + write-host $_.Exception.ToString() + } + + $rs = $resp.GetResponseStream() + [System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs + [string] $results = $sr.ReadToEnd() + + return $results +} + + + +main +