Skip to content

Instantly share code, notes, and snippets.

@elight
Last active August 29, 2015 14:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elight/7ec992820859af166835 to your computer and use it in GitHub Desktop.
Save elight/7ec992820859af166835 to your computer and use it in GitHub Desktop.
# containers
cf.containers.create("new_container")
cf.containers.create("new_container", metadata: { "you're on your own here bud": "because you wanted all of the power" }) # Should we even offer metadata mutation at create time????
container = cf.containers["my-test-dir"]
container.delete
# metadata (Hash-like protocol)
container.metadata # Return a Hash of the metadata less the X-Container-Meta- prefixes
container.metadata["price"] = "4.20"
container.metadata.delete("price")
.readers=(*args) # Set list of users with container read privileges
.readers
.writers=(*args) # Set list of users with container read privileges
.writers
.enable_versioning(versions_container = "versions")
.disable_versioning # TODO: Try "X-Remove-Versions-Location" first to see if we support it and then get back to Anne
container.sync_to(remote_container_path, with_key: key)
container.disable_sync # Have to remove the sync key per http://openstack.10931.n7.nabble.com/SWIFT-how-to-deactivate-container-sync-for-a-particular-container-td5245.html#a5249
# files
container.all # up to 10_000
.all(limit: 100) # with optional limit
.find_by_name("foo")
.find_by_name("foo", limit:100)
.find_by_name_beginning_with("foo") # using the "prefix" feature
#file
# TBD
@smashwilson
Copy link

Random comments and 💭s :

  • Returning a "Hash-like" object for container.metadata feels like trouble to me. I'd rather have an extra method call to get a real, honest Hash explicitly with to_h than try to fake it like fog does with Array for its collections. To be clear, I'm fine with implementing #[] and #[]= but I feel like we should avoid attempting to be more "Hash-like" than that - we shouldn't support enumeration, etc. (Maybe this is what you already meant; just want to be sure.)
  • What are the timing semantics for metadata manipulation? Do accesses and deletions take effect immediately, or should there be a container.save analog? I tend to fall on the side of having some way to persist changes explicitly so that operations can be batched.
  • I hadn't actually heard about sync before. What does it do, just keep two containers in sync... ?
  • find_by_name_beginning_with is awkward. find_by_name_prefix?
  • We're using a fog-like cf.containers "collection" at the top level, but files are enumerated directly from the container with .all or .find_.*. I'd say pick one or the other for consistency: either "collection objects (preferably not "fake Arrays", see above) or "flat access":
# "Collection" objects
everything = cf.containers.list
some = cf.containers.list(page: 3, per_page: 300)
container = cf.containers['specific-one']

container.files.list
container.files.list(prefix: 'foo')
container.files['specific-one']

# OR

# list methods
everything = cf.list_containers
some = cf.list_containers(page: 3, per_page: 300)
container = cf.container_named('specific_one')

container.list_files
container.list_files(prefix: 'foo')
container.file_named('specific_one')

I'm not sure which style I actually prefer - the former keeps API operations nicely organized by topic, while the latter is simpler and keeps the SDK more flat, which is easier to navigate.

@elight
Copy link
Author

elight commented Jul 16, 2014

  • {page: X, per_page: Y} doesn't work with our API because distributed system where CAP can result in inconsistencies in pagination. It's why OpenStack is using a "limit-marker" approach instead. I'm trying to hide those semantics (because I feel they deviate too much from the Rails/web dev world too much) by hiding the marker and letting the user specify a limit.
  • When I said Hash-like, I meant insofar as providing [] and []=(arg) methods and not necessarily making it Enumerable. Granted if being Enumerable is easy, I'd tend to go for it because idiomatic Ruby.
  • RE: batching operations, the question is where to draw the line. There are a lot of orthogonal pieces of metadata that are all updatable via the same API call. But they're orthogonal. Grouping them together in a single API call could make the SDK less clear.
  • I had initially considered the "list methods" approach, as you described it but I could see it leading to an explosion of methods on the CloudFiles class. I was hesitant to introduce the Containers class. I'm still considering axing it and pulling its behavior back into the CloudFiles class. My concern is that I can see CloudFiles becoming too cluttered already. I prematurely (my emphasis) extracted Containers as just a logical grouping for behaviors related to containers; it doesn't have any state of its own. So there's another SDK option:
file = cf["container-name"]["file-name"]

... but that starts to feel more like PERL or really bad Ruby as it its unclear to the reader what the first and second calls to [] are doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment