Skip to content

Create constructor(s) for creating Metadata from scratch #1459

Description

@jku

I think we should have method(s) that make creating new valid metadata from scratch easier as the current constructor has really been designed for the deserialization use case

  • They do not necessarily need to be in metadata.py (client has no need for them)
  • They should use reasonable defaults for everything possible, but take the arguments that are needed to create valid metadata

These would be useful for testing but also will make any repository tools and tutorials better.

Back of envelope proposal with a single method:

Metadata.new_with_defaults(signed_type: Type, expires: datetime) -> Metadata

This would do roughly

  • for all, set signed.version = 1
  • for all, set signed.spec_version = ".".join(SPECIFICATION_VERSION)
  • for all, set signatures = OrderedDict()
  • for root, set up all of the roles (but metadata might not be valid until keys are added)
  • for timestamp, create meta with snapshot Metafile with version = 1?
  • for snapshot, create empty meta dict: target MetaFiles must be added afterwards
  • for targets, create no delegations and empty targets

This might require a bit of experimentation to find a reasonable solution

Activity

  1. added
    backlogIssues to address with priority for current development goals
    repositoryRelated to the repository implementation
    on Jun 22, 2021
  2. jku commented on Sep 7, 2021

    @jku
    MemberAuthor

    To make this a bit more concrete: I have another PR that creates a root from scratch that looks like this:

    root = Root(1, SPEC_VER, expiry, {}, {}, True)
    for role in ["root", "timestamp", "snapshot", "targets"]:
        key, signer = self.create_key()
        root.roles[role] = Role([], 1)
        root.add_key(role, key)
        # store role:signer elsewhere
    self.md_root = Metadata(root, OrderedDict())

    Not pretty: it calls three constructors with at least one useless argument. It could look like

    self.md_root = Metadata.new_root(expiry)
    for role in self.md_root.signed.roles.keys():
        key, signer = self.create_key()
        self.md_root.signed.add_key(role, key)
        # store role:signer elsewhere

    better? other ideas?

  3. jku commented on Oct 28, 2021

    @jku
    MemberAuthor

    I have an alternative suggestion that would not add new API:

    md_root = Metadata(Root(expires=expiry_date))
    • support default None for constructor arguments where it makes sense: I think everything except expiry has a reasonable default (the meta dictionaries are debatable)
    • default values would not be used by deserialization code
    • using default value means the constructor should choose a good initial value for new metadata

    I think I like this. The only disadvantage is that it makes the constructor signatures even longer, but I can live with that.

    I think creating a minimal initial repo would look like

    targets = Metadata(Targets(expires=expiry_date))
    snapshot = Metadata(Snapshot(expires=expiry_date))
    timestamp = Metadata(Timestamp(expires=expiry_date))
    root = Metadata(Root(expires=expiry_date))
    
    for role in TOP_LEVEL_ROLE_NAMES:
        key, signer = create_key()
        root.signed.add_key(role, key)
        # TODO store signer
    
    # TODO: run snapshot/timestamp update
  4. joshuagl commented on Oct 28, 2021

    @joshuagl
    Member

    Nice. It's hard to argue with a one-liner!

  5. added this to the sprint 19 milestone on Mar 9, 2022
  6. assigned and unassigned on Mar 23, 2022
  7. modified the milestones: sprint 19, Sprint 20 on Mar 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

backlogIssues to address with priority for current development goalsrepositoryRelated to the repository implementationtesting

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions