59 lines
3.1 KiB
Python
59 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Repeat custody acceptance on a new pod, preserving all existing annotations."""
|
|
import argparse
|
|
import datetime
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
from pathlib import Path
|
|
|
|
HERE = Path(__file__).parent
|
|
s=importlib.util.spec_from_file_location('custody',HERE/'deploy_forge_custody.py')
|
|
m=importlib.util.module_from_spec(s)
|
|
s.loader.exec_module(m)
|
|
t=m.t
|
|
|
|
def main():
|
|
parser=argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--proposal',type=Path,required=True)
|
|
parser.add_argument('--receipt',type=Path,required=True)
|
|
parser.add_argument('--apply',action='store_true')
|
|
args=parser.parse_args()
|
|
p=json.loads(args.proposal.read_text())
|
|
for file,expected in p['executor_hashes'].items():
|
|
assert hashlib.sha256((HERE/file).read_bytes()).hexdigest()==expected,'executor-changed'
|
|
d=t.deployment()
|
|
assert t.digest(d['spec']['template'])==p['original_template_digest'],'deployment-changed'
|
|
original=json.loads((HERE/'receive-hook-proposal.json').read_text())
|
|
pod=t.target_pod(d,original)
|
|
annotations=dict(d['spec']['template']['metadata'].get('annotations',{}))
|
|
assert p['annotation_key'] not in annotations,'marker-preexists'
|
|
annotations[p['annotation_key']]=p['restart_marker']
|
|
patch=[{'op':'test','path':'/metadata/uid','value':p['deployment_uid']},
|
|
{'op':'test','path':'/metadata/resourceVersion','value':d['metadata']['resourceVersion']},
|
|
{'op':'add','path':'/spec/template/metadata/annotations','value':annotations}]
|
|
local=t.apply_locally(d,patch)
|
|
dry=t.patch_remote(patch,dry_run=True)
|
|
assert t.digest(local['spec']['template'])==t.digest(dry['spec']['template']),'dry-run-differs'
|
|
receipt={'proposal_id':p['proposal_id'],'revision':p['revision'],
|
|
'proposal_sha256':hashlib.sha256(args.proposal.read_bytes()).hexdigest(),
|
|
'at':datetime.datetime.now(datetime.timezone.utc).isoformat(),
|
|
'before_pod_uid':pod['pod_uid'],'dry_run_verified':True,'result':'dry-run-verified'}
|
|
args.receipt.write_text(json.dumps(receipt,indent=2)+'\n')
|
|
if args.apply:
|
|
applied=t.patch_remote(patch)
|
|
receipt.update(generation=applied['metadata']['generation'],result='rollout-started')
|
|
args.receipt.write_text(json.dumps(receipt,indent=2)+'\n')
|
|
after,new=t.wait_ready(original,t.TEMPLATE)
|
|
assert new['pod_uid']!=pod['pod_uid'],'pod-not-replaced'
|
|
assert t.digest(after['spec']['template'])==t.digest(local['spec']['template']),'deployment-changed'
|
|
raw=json.loads(t.native.command(['-n','forgejo','get','pod',new['pod'],'-o','json']))
|
|
status=next(x for x in raw['status']['initContainerStatuses'] if x['name']=='verify-secret-scanner')
|
|
assert status['state']['terminated']['exitCode']==0,'guard-not-completed'
|
|
receipt.update(after_pod_uid=new['pod_uid'],guard_completed=True,
|
|
after_probe=m.verify(new,'restart-'+str(after['metadata']['generation'])),result='verified')
|
|
args.receipt.write_text(json.dumps(receipt,indent=2)+'\n')
|
|
print(json.dumps(receipt))
|
|
|
|
if __name__=='__main__':
|
|
main()
|