Rework Build Site Agent binary UI with version auto-detect and rollback
Restructure the agent and tray binary blocks around an auto-detected current-release upload plus a separate legacy/rollback upload that stages a version without seizing current. Order staged versions by version number for the active-version dropdown, add a PE version detect route, and drop stale dev-status tags and manual-staging copy.
This commit is contained in:
@@ -51,15 +51,19 @@ def list_agent_binaries(binkey):
|
||||
@endpoints_bp.route('/siteagent/binaries/<binkey>', methods=['POST'])
|
||||
@require_permission('endpoints.agentpackage')
|
||||
def upload_agent_binary(binkey):
|
||||
"""Stage an uploaded binary as a new version and make it current.
|
||||
"""Stage an uploaded binary as a new version.
|
||||
|
||||
Expects multipart/form-data with a 'file' upload and a 'version' field. The
|
||||
version must be a strict dotted-numeric string (for example 1.6.3) so it is
|
||||
safe as a directory name and orderable. The upload must be a Windows PE
|
||||
executable. Older versions past the retention window are pruned, but never
|
||||
the current one.
|
||||
the current one. By default the upload becomes the current staged build; send
|
||||
makecurrent=false to stage a rollback/legacy build that joins the version
|
||||
list without displacing the active current.
|
||||
"""
|
||||
version = (request.form.get('version') or '').strip()
|
||||
makecurrent = (request.form.get('makecurrent') or 'true').strip().lower()
|
||||
makecurrent = makecurrent not in ('false', '0', 'no')
|
||||
if not agentstore.is_valid_binary_key(binkey):
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
@@ -90,7 +94,94 @@ def upload_agent_binary(binkey):
|
||||
'uploaded file is not a Windows executable',
|
||||
http_code=400)
|
||||
|
||||
result = agentstore.store_version(binkey, version, data)
|
||||
result = agentstore.store_version(binkey, version, data,
|
||||
make_current=makecurrent)
|
||||
return success_response({
|
||||
'binary': binkey,
|
||||
'current': result['current'],
|
||||
'versions': result['versions'],
|
||||
})
|
||||
|
||||
|
||||
@endpoints_bp.route('/siteagent/binaries/<binkey>/detect', methods=['POST'])
|
||||
@require_permission('endpoints.agentpackage')
|
||||
def detect_agent_binary_version(binkey):
|
||||
"""Read the PE file version of an uploaded EXE without staging it.
|
||||
|
||||
The Build Site Agent page calls this on file-select so the version field is
|
||||
prefilled from the binary's own version resource - the operator does not
|
||||
have to read the EXE properties by hand for a current-release upload.
|
||||
Returns {version} which is null when the file carries no readable version.
|
||||
"""
|
||||
if not agentstore.is_valid_binary_key(binkey):
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
'binkey must be one of: agent, tray',
|
||||
http_code=400)
|
||||
|
||||
upload = request.files.get('file')
|
||||
if upload is None or not upload.filename:
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
'a file upload is required',
|
||||
http_code=400)
|
||||
|
||||
data = upload.read(_MAX_UPLOAD_BYTES + 1)
|
||||
if len(data) > _MAX_UPLOAD_BYTES:
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
'uploaded binary exceeds the size limit',
|
||||
http_code=400)
|
||||
if not agentstore.looks_like_pe(data):
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
'uploaded file is not a Windows executable',
|
||||
http_code=400)
|
||||
|
||||
return success_response({
|
||||
'binary': binkey,
|
||||
'version': agentstore.read_pe_file_version(data),
|
||||
})
|
||||
|
||||
|
||||
@endpoints_bp.route('/siteagent/binaries/<binkey>/adopt', methods=['POST'])
|
||||
@require_permission('endpoints.agentpackage')
|
||||
def adopt_legacy_agent_binary(binkey):
|
||||
"""Adopt the unmanaged legacy flat file into the version store.
|
||||
|
||||
The pre-versioning install dropped a single shopdbagent.exe (or tray exe)
|
||||
straight under siteagent/. This copies that file in as a real staged version
|
||||
so it shows a version and joins retention, without the operator having to
|
||||
re-upload it. The version comes from the request when the binary carries no
|
||||
readable PE version resource; otherwise the detected version is used.
|
||||
"""
|
||||
if not agentstore.is_valid_binary_key(binkey):
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
'binkey must be one of: agent, tray',
|
||||
http_code=400)
|
||||
|
||||
status = agentstore.legacy_status(binkey)
|
||||
if status is None:
|
||||
return error_response(
|
||||
ErrorCodes.NOT_FOUND,
|
||||
'there is no unmanaged legacy binary to adopt',
|
||||
http_code=404)
|
||||
|
||||
source = request.get_json(silent=True) or {}
|
||||
version = (source.get('version') or status.get('version') or '').strip()
|
||||
if not agentstore.is_valid_version(version):
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
'version must be a dotted-numeric string such as 1.6.3',
|
||||
http_code=400)
|
||||
|
||||
result = agentstore.adopt_legacy(binkey, version)
|
||||
if result is None:
|
||||
return error_response(
|
||||
ErrorCodes.VALIDATION_ERROR,
|
||||
'the legacy binary could not be adopted',
|
||||
http_code=400)
|
||||
return success_response({
|
||||
'binary': binkey,
|
||||
'current': result['current'],
|
||||
|
||||
Reference in New Issue
Block a user