Skip to content
This repository has been archived by the owner on Jul 5, 2021. It is now read-only.

Add a flag to output data in JSON #45

Open
megCanicalKb opened this issue Aug 23, 2015 · 8 comments
Open

Add a flag to output data in JSON #45

megCanicalKb opened this issue Aug 23, 2015 · 8 comments
Assignees
Milestone

Comments

@megCanicalKb
Copy link

It would be nice to have a way to output the data in JSON to make it machine-parsable.

The use case here is to have a script that operates at a high-level while glacieruploader handles all of the operations/credentials.

Part of the changes that seems to be done include:

  • adding an option: "--json-output" and "-j"
  • redirecting the logging output to the error stream (to separate data and logs)
  • passing a new boolean to all commands: json_output
  • displaying in JSON when asked
@MoriTanosuke
Copy link
Owner

Good idea. I'm using more and more JSON output myself, so I can understand the usecase. Will see how easy it is to add JSON.

Thanks for the feedback!

@MoriTanosuke
Copy link
Owner

I added https://github.com/MoriTanosuke/glacieruploader/blob/master/src/main/java/de/kopis/glacier/printers/VaultPrinter.java pretty early, but it's hardcoded in a lot of places and probably not fit for the task.

At the moment the Commands do not output anything, just logging. Also there is no return value, so probably the exec method https://github.com/MoriTanosuke/glacieruploader/blob/master/src/main/java/de/kopis/glacier/commands/AbstractCommand.java#L74 needs to return an optional CommandResult to https://github.com/MoriTanosuke/glacieruploader/blob/master/src/main/java/de/kopis/glacier/GlacierUploader.java#L111 where I can then instantiate a new CommandPrinter with a JSON implementation. Will take a closer look in the evening.

@megCanicalKb
Copy link
Author

I've got a working prototype that works but i'm not a big fan of having to have the printer have a switch for raw/json.

I also had to make it output an array of JSON objects instead so I used a single instance of the printer and buffered the output until it's flushed. The auto-flush is ensure using the try-with-resource block which works nicely.

I'm thinking of keeping the printers but trying to have different classes and have something along the lines:

  • VaultPrinter (abstract)
  • VaultTextPrinter
  • VaultJSONPrinter
  • VaultPrinterFactory

It might be over-engineering the thing :-)

@megCanicalKb
Copy link
Author

I'll put theses changes up tomorrow night (PST time).

@MoriTanosuke
Copy link
Owner

Nice, that would be a great starting point. 👍
I'd expect a major refactoring for this in any case, so I'll start thinking about it as well.

@MoriTanosuke MoriTanosuke changed the title Adda flag to output data in JSON Add a flag to output data in JSON Aug 24, 2015
@MoriTanosuke
Copy link
Owner

What comes to mind first is a modification on the interface for AbstractCommand like this:

public abstract Optional<CommandResult> exec(OptionSet options, GlacierUploaderOptionParser optionParser);

Then all commands can return a CommandResult with a definitive status and a custom message. Probably an exception as well. Could look like this:

package de.kopis.glacier.commands;

import com.amazonaws.AmazonClientException;

public class CommandResult {

    public enum CommandResultStatus {
        SUCCESS,
        FAILURE,
        UNKNOWN
    }

    private final String message;
    private final CommandResultStatus status;
    private Exception exception;

    public CommandResult(CommandResultStatus failure, String s, AmazonClientException exception) {
        this(failure, s);
        this.exception = exception;
    }

    public CommandResult(CommandResultStatus status, String message) {
        this.status = status;
        this.message = message;
    }

    public Exception getException() {
        return exception;
    }

    public String getMessage() {
        return message;
    }

    public CommandResultStatus getStatus() {
        return status;
    }
}

There should still be something like a XXX, maybe like this:

package de.kopis.glacier.printers;

import de.kopis.glacier.commands.CommandResult;

import java.io.PrintStream;

public class JsonCommandResultPrinter {
    public void print(PrintStream out, CommandResult result) {
        //TODO create JSON representation of CommandResult
    }
}

That way the GlacierUploader can still use different implementations, switchable by command line parameters at https://github.com/MoriTanosuke/glacieruploader/blob/master/src/main/java/de/kopis/glacier/GlacierUploader.java#L111

I'll give it a go and see how far I come.

@Megra Does this sound like what you had in mind in any case ❓

@MoriTanosuke MoriTanosuke added this to the 0.1.0 milestone Aug 24, 2015
@MoriTanosuke MoriTanosuke self-assigned this Aug 24, 2015
MoriTanosuke added a commit that referenced this issue Aug 24, 2015
This is meant as a way to have commands return an exit status and probably display it as JSON. See #45
@MoriTanosuke
Copy link
Owner

Ok, I pushed my local branch. See https://github.com/MoriTanosuke/glacieruploader/tree/optional-command-responses for my changes so far and let me know what you think. I'll leave the branch open until this issue is solved.

@MoriTanosuke
Copy link
Owner

I pushed a small change to the branch and https://github.com/MoriTanosuke/glacieruploader/blob/optional-command-responses/src/main/java/de/kopis/glacier/GlacierUploader.java#L119 now takes the CommandResult and prints it to STDOUT.

This is what I got for an invalid command:

INFO  Using end point: https://glacier.eu-west-1.amazonaws.com
INFO  Creating vault myvaultname...
ERROR Couldn't create vault.
{status: 'FAILURE', message: 'Can not create vault: The security token included in the request is invalid. (Service: AmazonGlacier; Status Code: 403; Error Code: UnrecognizedClientException; Request ID: Uh0rH-Z7UTmUzmIv1YlJ3FR-MNZhUZy1yNC81yipzEza4sc)', requestId: 'Uh0rH-Z7UTmUzmIv1YlJ3FR-MNZhUZy1yNC81yipzEza4sc', exception: 'class com.amazonaws.AmazonServiceException'}

The first 3 lines are from my logging configuration. The last line prints the result as a JSON String. If there is a more information from the Amazon classes available, there would also be a field originalMessage with more information.

I also added the request ID in its own field in the JSON for easier access. Should be useful if a script has to remember or report those errors.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants