Commit graph

53 commits

Author SHA1 Message Date
Pat Gavlin e884c63104 Extract a Pulumi API client.
These changes refactor direct interactions with the Pulumi API out of
the cloud backend and into a subpackage, `pkg/backend/cloud/client`.
This package exposes a slightly higher-level API that takes care of
calculating paths, performing HTTP calls, and occasionally wrapping
multiple physical calls into a single logical call (notably the creation
of an update and the upload of its program).

This is primarily intended as preparation for some of the changes
suggested in the feedback for #1067.
2018-03-21 16:45:54 -07:00
Pat Gavlin a23b10a9bf
Update the copyright end date to 2018. (#1068)
Just what it says on the tin.
2018-03-21 12:43:21 -07:00
Justin Van Patten 8906731315
Adds a pulumi new command to scaffold a project (#1008)
This adds a `pulumi new` command which makes it easy to quickly
automatically create the handful of needed files to get started building
an empty Pulumi project.

Usage:

```
$ pulumi new typescript
```

Or you can leave off the template name, and it will ask you to choose
one:

```
$ pulumi new
Please choose a template:
> javascript
  python
  typescript
```
2018-03-09 15:27:55 -08:00
Matt Ellis db079b1b0a Emit richer events for resource steps
The engine now emits events with richer metadata during the
ResourceOutputs and ResourcePre callbacks. The CLI can then use this
information to decide if it should display the event or not and how
much of the event to display.

Options dealing with what to display and how to display it have moved
into the CLI and the engine now emits all information for each event.
2018-03-09 13:11:42 -08:00
Matt Ellis 4e2f94df95 Remove UpdateOptions.ShowConfig
The engine now unconditionally emits a new type of event, a
PreludeEvent, which contains the configuration for a stack as well as
an indication if the stack is being previewed or updated. The
responsibility for interpreting the --show-config flag on the command
line is now handled by the CLI, which uses this to decide if it should
print the configuration or not, and then writes the "Previewing
changes" or "Deploying chanages" header.
2018-03-09 11:13:06 -08:00
Matt Ellis d58bc719c4
Merge pull request #995 from pulumi/fix-923
Eliminate the superfluous ":config" part of config keys
2018-03-09 10:14:51 -08:00
Joe Duffy 96d4cca4c8
Add deployment to UpdateInfo (#1013)
This change prepares to add optional full deployment checkpoints to
the UpdateInfo payloads returned by the service.
2018-03-08 13:56:59 -08:00
Matt Ellis 5dfd720bc3 Remove config.AsModuleMember()
This API was introduced to aid the refactoring, but it isn't something
we want to support long term. Remove it and for a few places, push
passing config.Key around more, instead of converting to the old type
eagerly.
2018-03-08 10:52:25 -08:00
Matt Ellis 81a273c7bb Change represention of config.Key
config.Key has become a pair of namespace and name. Because the whole
world has not changed yet, there continues to be a way to convert
between a tokens.ModuleMember and config.Key, however now sometime the
conversion from tokens.ModuleMember can fail (when the module member
is not of the form `<package>:config:<name>`).
2018-03-08 10:52:25 -08:00
Matt Ellis 7c39620e9a Introduce config.Key
Right now, config.Key is a type alias for tokens.ModuleMember. I did a
pass over the codebase such that we use config.Key everywhere it
looked like the value did not leak to some external process (e.g a
resource provider or a langhost).

Doing this makes it a little clearer (hopefully) where code is
depending on a module member structure (e.g. <package>:config:<value>)
instead of just an opaque type.
2018-03-08 10:52:25 -08:00
Joe Duffy caceeea290
Reintroduce untyped deployments (#996)
By using untyped deployment structures via `json.RawMessage`, we can
support round-tripping between old CLI clients and newer servers, without
dropping possibly-important information on the floor.  I hadn't realized
this design goal with the original system, and after talking to @pgavlin,
I better realized the intent and that we want to preserve this.
2018-03-03 12:12:54 -08:00
Matt Ellis 207a9755d8 Rework configuration model
This change updates our configuration model to make it simpler to
understand by removing some features and changing how things are
persisted in files.

Notable changes:

- We've removed the notion of "workspace" vs "project"
  config. Now, configuration is always stored in a file next to
  `Pulumi.yaml` named `Pulumi.<stack-name>.yaml` (the same file we'd
  use for an other stack specific information we would need to persist
  in the future).
- We've removed the notion of project wide configuration. Every new
  stack gets a completely empty set of configuration and there's no
  way to share common values across stacks, instead the common value
  has to be set on each stack.

We retain some of the old code for the configuration system so we can
support upgrading a project in place. That will happen with the next
change.

This change fixes some issues and allows us to close some
others (since they are no longer possible).

Fixes #866
Closes #872
Closes #731
2018-02-28 17:30:50 -08:00
Matt Ellis d99f9457b0 Deprecate old configuration model
We are going to be changing the configuration model. To begin, let's
take most of the existing stuff and mark it as "deprecated" so we can
keep the existing behavior (to help transition newer code forward)
while making it clear what APIs should not be called in the
implementation of `pulumi` itself.
2018-02-28 17:25:09 -08:00
joeduffy 2362d45a5c Eliminate type redundancy
Despite our good progress moving towards having an apitype package,
where our exchange types live and can be shared among the engine and
our services, there were a few major types that were still duplciated.
Resource was the biggest example -- and indeed, the apitype varirant
was missing the new Dependencies property -- but there were others,
like Manfiest, PluginInfo, etc.  These too had semi-random omissions.

This change merges all of these types into the apitype package.  This
not only cleans up the redundancy and missing properties, but will
"force the issue" with respect to keeping them in sync and properly
versioning the information in a backwards compatible way.

The resource/stack package still exists as a simple marshaling layer
to and from the engine's core data types.

Finally, I've made the controversial change to share the actual
Deployment data structure at the apitype layer also.  This will force
us to confront differences in that data structure similarly, and will
allow us to leverage the strong typing throughout to catch issues.
2018-02-28 12:44:55 -08:00
Joe Duffy 811759fb77
Fix missing emojis on Windows (#966)
I was reminded of this yesterday with unprintable characters as I
debugged some things on Windows.  Inspired by Yarn, this change adds
a new flag --emoji (-e for short) that can be used to control whether
we show ASCII-only characters or not in the console.  On Mac, it
defaults to true, and on Windows and Linux, it defaults to false.

This also brings back the retro ASCII-friendly progress spinner
when --emoji is disabled.
2018-02-21 09:42:06 -08:00
joeduffy e5e58fd5ec Fix history command URL
This is a minor improvement on https://github.com/pulumi/pulumi/issues/965,
but we clearly have a lot more work to do (captured in that work item).
2018-02-20 18:31:25 -08:00
joeduffy 932e755305 Move plugins to their own directories
Prior to this change, we had a flat list of files in the
~/.pulumi/plugins directory.  This was simple but unfortunately
too naive, since we in fact have multi-file plugins already.
Dumping them in the same directory increases the risk of a
collision.  Instead, let's put them in their own directories.

This means, for example, you'll see things like

    ~/.pulumi/plugins/
        resource-aws-v0.11.0-dev-8-g57a0d62/
            README.txt
            pulumi-resource-aws

Notice that the binary name stays the same -- e.g., in this
case pulumi-resource-aws -- and does not include the version.
This makes it simple to add it to your $PATH in the usual ways
and have it loaded as a preferred location.
2018-02-19 09:31:00 -08:00
joeduffy 90ebca4aea Fix up API URLs
The API/REST logic auto-prepended "/api", which we don't want
for the release downloads.  This change just alters callsites
to specify the full path (which I prefer being explicit anyway).
2018-02-18 08:08:15 -08:00
joeduffy c1752d357e Implement basic plugin management
This change implements basic plugin management, but we do not yet
actually use the plugins for anything (that comes next).

Plugins are stored in `~/.pulumi/plugins`, and are expected to be
in the format `pulumi-<KIND>-<NAME>-v<VERSION>[.exe]`.  The KIND is
one of `analyzer`, `language`, or `resource`, the NAME is a hyphen-
delimited name (e.g., `aws` or `foo-bar`), and VERSION is the
plugin's semantic version (e.g., `0.9.11`, `1.3.7-beta.a736cf`, etc).

This commit includes four new CLI commands:

* `pulumi plugin` is the top-level plugin command.  It does nothing
  but show the help text for associated child commands.

* `pulumi plugin install` can be used to install plugins manually.
  If run with no additional arguments, it will compute the set of
  plugins used by the current project, and download them all.  It
  may be run to explicitly download a single plugin, however, by
  invoking it as `pulumi plugin install KIND NAME VERSION`.  For
  example, `pulumi plugin install resource aws v0.9.11`.  By default,
  this command uses the cloud backend in the usual way to perform the
  download, although a separate URL may be given with --cloud-url,
  just like all other commands that interact with our backend service.

* `pulumi plugin ls` lists all plugins currently installed in the
  plugin cache.  It displays some useful statistics, like the size
  of the plugin, when it was installed, when it was last used, and
  so on.  It sorts the display alphabetically by plugin name, and
  for plugins with multiple versions, it shows the newest at the top.
  The command also summarizes how much disk space is currently being
  consumed by the plugin cache.  There are no filtering capabilities yet.

* `pulumi plugin prune` will delete plugins from the cache.  By
  default, when run with no arguments, it will delete everything.
  It may be run with additional arguments, KIND, NAME, and VERSION,
  each one getting more specific about what it will delete.  For
  instance, `pulumi plugin prune resource aws` will delete all AWS
  plugin versions, while `pulumi plugin prune resource aws <0.9`
  will delete all AWS plugins before version 0.9.  Unless --yes is
  passed, the command will confirm the deletion with a count of how
  many plugins will be affected by the command.

We do not yet actually download plugins on demand yet.  That will
come in a subsequent change.
2018-02-18 08:08:15 -08:00
Joe Duffy 776a76dffd
Make some stack-related CLI improvements (#947)
This change includes a handful of stack-related CLI formatting
improvements that I've been noodling on in the background for a while,
based on things that tend to trip up demos and the inner loop workflow.

This includes:

* If `pulumi stack select` is run by itself, use an interactive
  CLI menu to let the user select an existing stack, or choose to
  create a new one.  This looks as follows

      $ pulumi stack select
      Please choose a stack, or choose to create a new one:
        abcdef
        babblabblabble
      > currentlyselected
        defcon
        <create a new stack>

  and is navigated in the usual way (key up, down, enter).

* If a stack name is passed that does not exist, prompt the user
  to ask whether s/he wants to create one on-demand.  This hooks
  interesting moments in time, like `pulumi stack select foo`,
  and cuts down on the need to run additional commands.

* If a current stack is required, but none is currently selected,
  then pop the same interactive menu shown above to select one.
  Depending on the command being run, we may or may not show the
  option to create a new stack (e.g., that doesn't make much sense
  when you're running `pulumi destroy`, but might when you're
  running `pulumi stack`).  This again lets you do with a single
  command what would have otherwise entailed an error with multiple
  commands to recover from it.

* If you run `pulumi stack init` without any additional arguments,
  we interactively prompt for the stack name.  Before, we would
  error and you'd then need to run `pulumi stack init <name>`.

* Colorize some things nicely; for example, now all prompts will
  by default become bright white.
2018-02-16 15:03:54 -08:00
Joe Duffy 55e4dbe835
Update spinner to use modern ASCII/emoji art (#942) 2018-02-15 18:22:17 -08:00
Joe Duffy 902d646215
Rename package to project (#935)
This addresses pulumi/pulumi#446: what we used to call "package" is
now called "project".  This has gotten more confusing over time, now
that we're doing real package management.

Also fixes pulumi/pulumi#426, while in here.
2018-02-14 13:56:16 -08:00
Pat Gavlin 881393146b Remove update event waits. 2018-02-09 09:43:04 -08:00
pat@pulumi.com e8e0ae9bb4 Wait between calls to fetch update logs.
As it stands, we currently hammer the service's update logs endpoint in
a tight loop while waiting for a deployment to complete. This is not
necessary, and can indeed be deletrious to the user experience: it
appears that this may be exacerbating some mysterious 500 responses from
API gateway.

These changes add a brief sleep in the relevant loop that waits for 5
seconds if the last call produced new log entries or 15 seconds if it
did not.

Fixes #844.
2018-02-07 16:57:05 -08:00
Matt Ellis 818246a708 Allow control of uploaded archive root in Pulumi.yaml
Previously, when uploading a projectm to the service, we would only
upload the folder rooted by the Pulumi.yaml for that project. This
worked well, but it meant that customers needed to structure their
code in a way such that Pulumi.yaml was always as the root of their
project, and if they wanted to share common files between two projects
there was no good solution for doing this.

This change introduces an optional piece of metadata, named context,
that can be added to Pulumi.yaml, which allows controlling the root
folder used for computing the root folder to archive from.  When it is
set, it is combined with the location of the Pulumi.yaml file for the
project we are uploading and that folder is uses as the root of what
we upload to the service.

Fixes: #574
2018-01-31 16:22:58 -08:00
Matt Ellis 39dbdc98e9 Clean up colorization logic
The existing logic would flow colorization information into the
engine, so depending on the settings in the CLI, the engine may or may
not have emitted colorized events. This coupling is not great and we
want to start moving to a world where the presentation happens
exclusively at the CLI level.

With this change, the engine will always produce strings that have the
colorization formatting directives (i.e. the directives that
reconquest/loreley understands) and the CLI will apply
colorization (which could mean either running loreley to turn the
directives into ANSI escape codes, or drop them or retain them, for
debuging purposes).

Fixes #742
2018-01-31 15:46:14 -08:00
Chris Smith 4c217fd358
Add "pulumi history" command (#826)
This PR adds a new `pulumi history` command, which prints the update history for a stack.

The local backend stores the update history in a JSON file on disk, next to the checkpoint file. The cloud backend simply provides the update metadata, and expects to receive all the data from a (NYI) `/history` REST endpoint.

`pkg/backend/updates.go` defines the data that is being persisted. The way the data is wired through the system is adding a new `backend.UpdateMetadata` parameter to a Stack/Backend's `Update` and `Destroy` methods.

I use `tests/integration/stack_outputs/` as the simple app for the related tests, hence the addition to the `.gitignore` and fixing the name in the `Pulumi.yaml`.

Fixes #636.
2018-01-24 18:22:41 -08:00
Matt Ellis ce05cce77f Provide a rudimentary progress spinner
Previously, the `pulumi` tool did not show any indication of progress
when doing a deployment. Combined with the fact that we do not create
resources in parallel it meant that sometime `pulumi` would appear to
hang, when really it was just waiting on some resource to be created
in AWS. In addition, some AWS resources take a long time to create and
CI systems like travis will kill the job if there is no output. This
causes us (and our customers) to have to do crazy dances where we
launch shell scripts that write a dot to the console every once in a
while so we don't get killed. While we plan to overhaul the output
logic (see #617), we take a first step towards interactivity by simply
having a nice little spinner (in the interactive case) and when run
non interactive have `pulumi` print a message that it is still
working.

Fixes #794
2018-01-22 14:21:08 -08:00
Chris Smith a4f087460f
Fix false-positives in login verification (#825)
Surprisingly `pulumi login -c https://google.com` would succeed. This was because we were too lax in our way of validating credentials. We take the provided cloud URL and call the "GetCurrentUserHandler" method. But we were only checking that it returned a successful response, not that it was actually valid JSON.

So in the "https://google.com" case, Google returned HTML describing a 404 error, but since the sever response was 200, the Pulumi CLI assumed things were on the up and up.

We now parse the response as JSON, and confirm the response has a `name` property that is non-nil. This heuristic covers the majority of false-positive cases, but without us needing to move all of the service's API shape for users, which includes organizations, which includes Clouds, etc. into `pulumi`.

Fixes https://github.com/pulumi/pulumi-service/issues/457. As an added bonus, we now return a much more useful error message.
2018-01-20 19:11:38 -08:00
Chris Smith 3a3d0698ae
Surface update options to the service (#806)
This PR surfaces the configuration options available to updates, previews, and destroys to the Pulumi Service. As part of this I refactored the options to unify them into a single `engine.UpdateOptions`, since they were all overlapping to various degrees.

With this PR we are adding several new flags to commands, e.g. `--summary` was not available on `pulumi destroy`.

There are also a few minor breaking changes.

- `pulumi destroy --preview` is now `pulumi destroy --dry-run` (to match the actual name of the field).
- The default behavior for "--color" is now `Always`. Previously it was `Always` or `Never` based on the value of a `--debug` flag. (You can specify `--color always` or `--color never` to get the exact behavior.)

Fixes #515, and cleans up the code making some other features slightly easier to add.
2018-01-18 11:10:15 -08:00
khyperia 08f3c623e6
Fix some style issues 2018-01-11 12:05:08 -08:00
khyperia 0f73b8c395
Move types to pulumi-service 2018-01-11 11:51:31 -08:00
khyperia f455689bd4
Add apitypes from pulumi-ppc 2018-01-10 15:43:44 -08:00
khyperia 3c644d243f
Create apitype package 2018-01-10 15:04:55 -08:00
pat@pulumi.com c56e716c31 Refactor the engine's entrypoints.
These changes refactor the engine's entrypoints--Deploy, Destroy, and
Preview--to be update-centric rather than stack-centric. Each of these
methods now takes a value of a new type, Update, that abstracts away the
vagaries of fetching and maintaining the update's state. This
refactoring also reinforces Pulumi.yaml as a CLI concept rather than an
engine concept; the CLI is now the only reader/writer of this format.

These changes will smooth the way for a few refactorings on the service
side that will aid in update isolation.
2018-01-08 14:15:16 -08:00
Matthew Riley 9e3976513c AssertNoError instead of Assert(err == nil)
This may not be exhaustive, but I replaced all instances I could find.
2018-01-08 13:46:21 -08:00
pat@pulumi.com b96217341f Add the ability to {ex,im}port a stack's deployment.
These changes add the ability to export a stack's latest deployment or
import a new deployment to a stack via the Pulumi CLI. These
capabilities are exposed by two new verbs under `stack`:
- export, which writes the current stack's latest deployment to stdout
- import, which reads a new deployment from stdin and applies it to the
  current stack.

In the local case, this simply involves reading/writing the stack's
latest checkpoint file. In the cloud case, this involves hitting two new
endpoints on the service to perform the export or import.
2018-01-05 16:22:31 -08:00
Joe Duffy 86c1e7ad39
Merge pull request #764 from pulumi/763_wait_for_update_resiliency
Make the CLI's waitForUpdates more resilient to transient failure
2017-12-27 06:34:08 -08:00
joeduffy 87079589f1 Use the retry framework for REST API retries
This change incorporates feedback on https://github.com/pulumi/pulumi/pull/764,
in addition to refactoring the retry logic to use our retry framework rather
than hand-rolling it in the REST API code.  It's a minor improvement, but at
least lets us consolidate some of this logic which we'll undoubtedly use more
of over time.
2017-12-26 10:24:08 -08:00
Luke Hoban 56fd8bc257
Fix REST API calls for encrypt/decrypt (#767)
The merge of two recent changes seems to have led to these calls invoking the API incorrectly.
2017-12-26 09:42:42 -08:00
joeduffy db5318b0a5 Make the CLI's waitForUpdates more resilient to transient failure
We saw an issue where a user was mid-update, and got a networking
error stating `read: operation timed out`.  We believe this was simply
a local client error, due to a flaky network.  We should be resilient
to such things during updates, particularly when there's no way to
"reattach" to an in-progress udpate (see pulumi/pulumi#762).

This change accomplishes this by changing our retry logic in the
cloud backend's waitForUpdates function.  Namely:

* We recognize three types of failure, and react differently:

    - Expected HTTP errors.  For instance, the 504 Gateway Timeouts
      that we already retried in the face of.  In these cases, we will
      silently retry up to 10 times.  After 10 times, we begin warning
      the user just in case this is a persistent condition.

    - Unexpected HTTP errors.  The CLI will quit immediately and issue
      an error to the user, in the usual ways.  This covers
      Unauthorized among other things.  Over time, we may find that we
      want to intentionally move some HTTP errors into the above.

    - Anything else.  This covers the transient networking errors case
      that we have just seen.  I'll admit, it's a wide net, but any
      instance of this error issues a warning and it's up to the user
      to ^C out of it.  We also log the error so that we'll see it if
      the user shares their logs with us.

* We implement backoff logic so that we retry very quickly (100ms)
  on the first failure, and more slowly thereafter (1.5x, up to a max
  of 5 seconds).  This helps to avoid accidentally DoSing our service.
2017-12-26 09:40:51 -08:00
Pat Gavlin e4d9eb6fd3 Support secrets for cloud stacks.
Use the new {en,de}crypt endpoints in the Pulumi.com API to secure
secret config values. The ciphertext for a secret config value is bound
to the stack to which it applies and cannot be shared with other stacks
(e.g. by copy/pasting it around in Pulumi.yaml). All secrets will need
to be encrypted once per target stack.
2017-12-22 07:59:27 -08:00
Luke Hoban 7cc782e856
Add support for pulumi logs --since when targeting cloud backend (#756)
Hooks up the CLI to be able to pass query parameters through to the
service.

Part of pulumi/pulumi-service#431.
2017-12-21 17:16:45 -08:00
Joe Duffy f0c28db639
Attempt to fix colorization (#740)
Our recent changes to colorization changed from a boolean to a tri-valued
enum (Always, Never, Raw).  The events from the service, however, are still
boolean-valued.  This changes the message payload to carry the full values.
2017-12-18 11:42:32 -08:00
Joe Duffy 6dc16a5548
Make cloud authentication more intuitive (#738)
The prior behavior with cloud authentication was a bit confusing
when authenticating against anything but https://pulumi.com/.  This
change fixes a few aspects of this:

* Improve error messages to differentiate between "authentication
  failed" and "you haven't logged into the target cloud URL."

* Default to the cloud you're currently authenticated with, rather
  than unconditionally selecting https://pulumi.com/.  This ensures

      $ pulumi login -c https://api.moolumi.io
      $ pulumi stack ls

  works, versus what was currently required

      $ pulumi login -c https://api.moolumi.io
      $ pulumi stack ls -c https://api.moolumi.io

  with confusing error messages if you forgot the second -c.

* To do this, our default cloud logic changes to

    1) Prefer the explicit -c if supplied;

    2) Otherwise, pick the "currently authenticated" cloud; this is
       the last cloud to have been targeted with pulumi login, or
       otherwise the single cloud in the list if there is only one;

    3) https://pulumi.com/ otherwise.
2017-12-16 07:49:41 -08:00
Joe Duffy 36ab8f0087
Make config a little less error prone
As articulated in #714, the way config defaults to workspace-local
configuration is a bit error prone, especially now with the cloud
workflow being the default.  This change implements several improvements:

* First, --save defaults to true, so that configuration changes will
  persist into your project file.  If you want the old local workspace
  behavior, you can specify --save=false.

* Second, the order in which we applied configuration was a little
  strange, because workspace settings overwrote project settings.
  The order is changed now so that we take most specific over least
  specific configuration.  Per-stack is considered more specific
  than global and project settings are considered more specific
  than workspace.

* We now warn anytime workspace local configuration is used.  This
  is a developer scenario and can have subtle effects.  It is simply
  not safe to use in a team environment.  In fact, I lost an arm
  this morning due to workspace config... and that's why you always
  issue warnings for unsafe things.
2017-12-13 10:46:54 -08:00
joeduffy 664d4f3bfe Add a missing error propagation
If the service returns a 504, we happily keep looping around and
retrying until we get a valid update.  Unfortunately, we missed the
else condition, which is what happens when this isn't a 504, leading
us to swallow real errors (500 and the like).  Trivial fix.

Fixes pulumi/pulumi#712.
2017-12-13 08:33:11 -08:00
Joe Duffy d89a2b4e1f
Add a logout --all command (#673)
If a cloud you've previously authenticated with goes away -- as ours
sort of did, because the cloud endpoing in the CLI changed (to actually
be correct) -- then you can't logout without manually editing the
credentials file in your workspace.  This is a little annoying.  So,
rather than that, let's have a `pulumi logout --all` command that just
logs out of all clouds you are presently authenticated with.
2017-12-08 12:14:14 -08:00
Chris Smith 527a1c97e7 Fix panic with nil message entry 2017-12-08 10:21:25 -08:00
Chris Smith e104ebd7f6
Several fixes relating to Pulumi clouds and auth (#651)
- Fix #644 "Re-enable use of local dev stacks". Rather than trying to be smart about using "pulumi.com" and inferring "api.pulumi.com", we just use whatever cloud URL the user provides. (e.g. "http://localhost:8080") We can improve the user experience later by providing friendly names for these things upon login. So we can show "Pulumi" or "Contoso" instead of the URL -- but let's cross that bridge later.

- Fix #640, "Better error on `pulumi login`". We only provide the more friendly error about needing to login IFF you are trying to use an authenticated Pulumi API without having creds.
2017-12-07 10:59:20 -08:00