mirror of https://github.com/hashicorp/packer
commit
de53439fcf
@ -0,0 +1,132 @@
|
||||
package googlecompute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"google.golang.org/api/oauth2/v2"
|
||||
)
|
||||
|
||||
// StepImportOSLoginSSHKey imports a temporary SSH key pair into a GCE login profile.
|
||||
type StepImportOSLoginSSHKey struct {
|
||||
Debug bool
|
||||
TokeninfoFunc func(context.Context) (*oauth2.Tokeninfo, error)
|
||||
accountEmail string
|
||||
}
|
||||
|
||||
// Run executes the Packer build step that generates SSH key pairs.
|
||||
// The key pairs are added to the ssh config
|
||||
func (s *StepImportOSLoginSSHKey) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*Config)
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if !config.UseOSLogin {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// If no public key information is available chances are that a private key was provided
|
||||
// or that the user is using a SSH agent for authentication.
|
||||
if config.Comm.SSHPublicKey == nil {
|
||||
ui.Say("No public SSH key found; skipping SSH public key import for OSLogin...")
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
if s.TokeninfoFunc == nil {
|
||||
s.TokeninfoFunc = tokeninfo
|
||||
}
|
||||
|
||||
ui.Say("Importing SSH public key for OSLogin...")
|
||||
// Generate SHA256 fingerprint of SSH public key
|
||||
// Put it into state to clean up later
|
||||
sha256sum := sha256.Sum256(config.Comm.SSHPublicKey)
|
||||
state.Put("ssh_key_public_sha256", hex.EncodeToString(sha256sum[:]))
|
||||
|
||||
if config.account != nil {
|
||||
s.accountEmail = config.account.Email
|
||||
}
|
||||
|
||||
if s.accountEmail == "" {
|
||||
info, err := s.TokeninfoFunc(ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error obtaining token information needed for OSLogin: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.accountEmail = info.Email
|
||||
}
|
||||
|
||||
loginProfile, err := driver.ImportOSLoginSSHKey(s.accountEmail, string(config.Comm.SSHPublicKey))
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error importing SSH public key for OSLogin: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Replacing `SSHUsername` as the username have to be from OSLogin
|
||||
if len(loginProfile.PosixAccounts) == 0 {
|
||||
err := fmt.Errorf("Error importing SSH public key for OSLogin: no PosixAccounts available")
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Let's obtain the `Primary` account username
|
||||
ui.Say("Obtaining SSH Username for OSLogin...")
|
||||
var username string
|
||||
for _, account := range loginProfile.PosixAccounts {
|
||||
if account.Primary {
|
||||
username = account.Username
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if s.Debug {
|
||||
ui.Message(fmt.Sprintf("ssh_username: %s", username))
|
||||
}
|
||||
config.Comm.SSHUsername = username
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup the SSH Key that we added to the POSIX account
|
||||
func (s *StepImportOSLoginSSHKey) Cleanup(state multistep.StateBag) {
|
||||
config := state.Get("config").(*Config)
|
||||
driver := state.Get("driver").(Driver)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if !config.UseOSLogin {
|
||||
return
|
||||
}
|
||||
|
||||
fingerprint, ok := state.Get("ssh_key_public_sha256").(string)
|
||||
if !ok || fingerprint == "" {
|
||||
return
|
||||
}
|
||||
|
||||
ui.Say("Deleting SSH public key for OSLogin...")
|
||||
err := driver.DeleteOSLoginSSHKey(s.accountEmail, fingerprint)
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf("Error deleting SSH public key for OSLogin. Please delete it manually.\n\nError: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
ui.Message("SSH public key for OSLogin has been deleted!")
|
||||
}
|
||||
|
||||
func tokeninfo(ctx context.Context) (*oauth2.Tokeninfo, error) {
|
||||
svc, err := oauth2.NewService(ctx)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error initializing oauth service needed for OSLogin: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return svc.Tokeninfo().Context(ctx).Do()
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
package googlecompute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"google.golang.org/api/oauth2/v2"
|
||||
)
|
||||
|
||||
func TestStepImportOSLoginSSHKey_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepImportOSLoginSSHKey)
|
||||
}
|
||||
|
||||
func TestStepImportOSLoginSSHKey(t *testing.T) {
|
||||
tt := []struct {
|
||||
Name string
|
||||
UseOSLogin bool
|
||||
ExpectedEmail string
|
||||
ExpectedAction multistep.StepAction
|
||||
PubKeyExpected bool
|
||||
}{
|
||||
{
|
||||
Name: "UseOSLoginDisabled",
|
||||
ExpectedAction: multistep.ActionContinue,
|
||||
},
|
||||
{
|
||||
Name: "UseOSLoginWithAccountFile",
|
||||
UseOSLogin: true,
|
||||
ExpectedAction: multistep.ActionContinue,
|
||||
ExpectedEmail: "raffi-compute@developer.gserviceaccount.com",
|
||||
PubKeyExpected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
state := testState(t)
|
||||
step := new(StepImportOSLoginSSHKey)
|
||||
defer step.Cleanup(state)
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
config.UseOSLogin = tc.UseOSLogin
|
||||
|
||||
if tc.PubKeyExpected {
|
||||
config.Comm.SSHPublicKey = []byte{'k', 'e', 'y'}
|
||||
}
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
|
||||
if step.accountEmail != tc.ExpectedEmail {
|
||||
t.Fatalf("expected accountEmail to be %q but got %q", tc.ExpectedEmail, step.accountEmail)
|
||||
}
|
||||
|
||||
if _, ok := state.GetOk("ssh_key_public_sha256"); !ok && tc.PubKeyExpected {
|
||||
t.Fatal("expected to see a public key")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepImportOSLoginSSHKey_withAccountFile(t *testing.T) {
|
||||
// default teststate contains an account file
|
||||
state := testState(t)
|
||||
step := new(StepImportOSLoginSSHKey)
|
||||
defer step.Cleanup(state)
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
config.UseOSLogin = true
|
||||
config.Comm.SSHPublicKey = []byte{'k', 'e', 'y'}
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
|
||||
fakeAccountEmail := "raffi-compute@developer.gserviceaccount.com"
|
||||
if step.accountEmail != fakeAccountEmail {
|
||||
t.Fatalf("expected accountEmail to be %q but got %q", fakeAccountEmail, step.accountEmail)
|
||||
}
|
||||
|
||||
pubKey, ok := state.GetOk("ssh_key_public_sha256")
|
||||
if !ok {
|
||||
t.Fatal("expected to see a public key")
|
||||
}
|
||||
|
||||
sha256sum := sha256.Sum256(config.Comm.SSHPublicKey)
|
||||
if pubKey != hex.EncodeToString(sha256sum[:]) {
|
||||
t.Errorf("expected to see a matching public key, but got %q", pubKey)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepImportOSLoginSSHKey_withNoAccountFile(t *testing.T) {
|
||||
state := testState(t)
|
||||
fakeAccountEmail := "testing@packer.io"
|
||||
step := &StepImportOSLoginSSHKey{
|
||||
TokeninfoFunc: func(ctx context.Context) (*oauth2.Tokeninfo, error) {
|
||||
return &oauth2.Tokeninfo{Email: fakeAccountEmail}, nil
|
||||
},
|
||||
}
|
||||
defer step.Cleanup(state)
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
config.account = nil
|
||||
config.UseOSLogin = true
|
||||
config.Comm.SSHPublicKey = []byte{'k', 'e', 'y'}
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
|
||||
if step.accountEmail != fakeAccountEmail {
|
||||
t.Fatalf("expected accountEmail to be %q but got %q", fakeAccountEmail, step.accountEmail)
|
||||
}
|
||||
|
||||
pubKey, ok := state.GetOk("ssh_key_public_sha256")
|
||||
if !ok {
|
||||
t.Fatal("expected to see a public key")
|
||||
}
|
||||
|
||||
sha256sum := sha256.Sum256(config.Comm.SSHPublicKey)
|
||||
if pubKey != hex.EncodeToString(sha256sum[:]) {
|
||||
t.Errorf("expected to see a matching public key, but got %q", pubKey)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepImportOSLoginSSHKey_withPrivateSSHKey(t *testing.T) {
|
||||
// default teststate contains an account file
|
||||
state := testState(t)
|
||||
step := new(StepImportOSLoginSSHKey)
|
||||
defer step.Cleanup(state)
|
||||
|
||||
config := state.Get("config").(*Config)
|
||||
config.UseOSLogin = true
|
||||
config.Comm.SSHPrivateKey = []byte{'k', 'e', 'y'}
|
||||
config.Comm.SSHPublicKey = nil
|
||||
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
|
||||
if step.accountEmail != "" {
|
||||
t.Fatalf("expected accountEmail to be unset but got %q", step.accountEmail)
|
||||
}
|
||||
|
||||
pubKey, ok := state.GetOk("ssh_key_public_sha256")
|
||||
if ok {
|
||||
t.Errorf("expected to not see a public key when using a dedicated private key, but got %q", pubKey)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/packer/builder/vsphere/driver"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/helper/ssh"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
// StepSshKeyPair executes the business logic for setting the SSH key pair in
|
||||
// the specified communicator.Config.
|
||||
type StepSshKeyPair struct {
|
||||
Debug bool
|
||||
DebugKeyPath string
|
||||
Comm *communicator.Config
|
||||
}
|
||||
|
||||
func (s *StepSshKeyPair) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
if s.Comm.Type != "ssh" || s.Comm.SSHPassword != "" {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
comment := fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
|
||||
if s.Comm.SSHPrivateKeyFile != "" {
|
||||
ui.Say("Using existing SSH private key for the communicator...")
|
||||
privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
kp, err := ssh.KeyPairFromPrivateKey(ssh.FromPrivateKeyConfig{
|
||||
RawPrivateKeyPemBlock: privateKeyBytes,
|
||||
Comment: comment,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.Comm.SSHPrivateKey = privateKeyBytes
|
||||
s.Comm.SSHKeyPairName = kp.Comment
|
||||
s.Comm.SSHTemporaryKeyPairName = kp.Comment
|
||||
s.Comm.SSHPublicKey = kp.PublicKeyAuthorizedKeysLine
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
if s.Comm.SSHAgentAuth {
|
||||
ui.Say("Using local SSH Agent to authenticate connections for the communicator...")
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui.Say("Creating ephemeral key pair for SSH communicator...")
|
||||
|
||||
if s.Comm.SSHTemporaryKeyPairName != "" {
|
||||
comment = s.Comm.SSHTemporaryKeyPairName
|
||||
}
|
||||
|
||||
kp, err := ssh.NewKeyPair(ssh.CreateKeyPairConfig{
|
||||
Comment: comment,
|
||||
Type: ssh.Rsa,
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.Comm.SSHKeyPairName = kp.Comment
|
||||
s.Comm.SSHTemporaryKeyPairName = kp.Comment
|
||||
s.Comm.SSHPrivateKey = kp.PrivateKeyPemBlock
|
||||
s.Comm.SSHPublicKey = kp.PublicKeyAuthorizedKeysLine
|
||||
s.Comm.SSHClearAuthorizedKeys = true
|
||||
|
||||
vm := state.Get("vm").(*driver.VirtualMachine)
|
||||
err = vm.AddPublicKeys(ctx, string(s.Comm.SSHPublicKey))
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("error saving temporary keypair in the vm: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say("Created ephemeral SSH key pair for communicator")
|
||||
|
||||
// If we're in debug mode, output the private key to the working
|
||||
// directory.
|
||||
if s.Debug {
|
||||
ui.Message(fmt.Sprintf("Saving communicator private key for debug purposes: %s", s.DebugKeyPath))
|
||||
// Write the key out
|
||||
if err := ioutil.WriteFile(s.DebugKeyPath, kp.PrivateKeyPemBlock, 0600); err != nil {
|
||||
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepSshKeyPair) Cleanup(state multistep.StateBag) {
|
||||
if s.Debug {
|
||||
if err := os.Remove(s.DebugKeyPath); err != nil {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error removing debug key '%s': %s", s.DebugKeyPath, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package command
|
||||
|
||||
import "strings"
|
||||
|
||||
func init() {
|
||||
spaghettiCarbonara = fixWindowsLineEndings(spaghettiCarbonara)
|
||||
lasagna = fixWindowsLineEndings(lasagna)
|
||||
tiramisu = fixWindowsLineEndings(tiramisu)
|
||||
}
|
||||
|
||||
func fixWindowsLineEndings(s string) string {
|
||||
return strings.ReplaceAll(s, "\n", " \r\n")
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
source "null" "chocolate" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
sources = ["null.chocolate"]
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo hi > provisioner.${build.ID}.txt"]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
inline = ["echo hi > post-processor.${build.ID}.txt"]
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
source "null" "chocolate" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
sources = ["null.chocolate"]
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = [
|
||||
"echo hi > provisioner.${build.ID}.txt",
|
||||
"echo hi > provisioner.${upper(build.ID)}.txt"
|
||||
]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
inline = [
|
||||
"echo hi > post-processor.${build.ID}.txt",
|
||||
"echo hi > post-processor.${upper(build.ID)}.txt"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
source "null" "chocolate" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
source "null" "banana" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
name = "vanilla"
|
||||
sources = ["null.chocolate"]
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo hi > vanilla.chocolate.provisioner.${build.ID}.txt"]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
inline = ["echo hi > vanilla.chocolate.post-processor.${build.ID}.txt"]
|
||||
}
|
||||
}
|
||||
|
||||
build {
|
||||
name = "apple"
|
||||
sources = ["null.chocolate"]
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo hi > apple.chocolate.provisioner.${build.ID}.txt"]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
inline = ["echo hi > apple.chocolate.post-processor.${build.ID}.txt"]
|
||||
}
|
||||
}
|
||||
|
||||
build {
|
||||
name = "sugar"
|
||||
sources = ["null.banana"]
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo hi > sugar.banana.provisioner.${build.ID}.txt"]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
inline = ["echo hi > sugar.banana.post-processor.${build.ID}.txt"]
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
source "null" "chocolate" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
source "null" "banana" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
name = "vanilla"
|
||||
sources = [
|
||||
"null.chocolate",
|
||||
"null.banana",
|
||||
]
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = [
|
||||
"echo hi > all.${build.ID}.txt",
|
||||
"echo hi > chocolate.${build.ID}.txt",
|
||||
"echo hi > banana.${build.ID}.txt"
|
||||
]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
only = ["null.chocolate"]
|
||||
inline = ["rm chocolate.${build.ID}.txt"]
|
||||
}
|
||||
post-processor "shell-local" {
|
||||
except = ["null.chocolate"]
|
||||
inline = ["rm banana.${build.ID}.txt"]
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
source "null" "chocolate" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
name = "vanilla"
|
||||
sources = ["null.chocolate"]
|
||||
|
||||
provisioner "shell-local" {
|
||||
inline = ["echo hi > provisioner.${build.ID}.txt"]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
inline = ["echo hi > post-processor.${build.ID}.txt"]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
|
||||
build {
|
||||
source "source.null.base" {
|
||||
name = "tiramisu"
|
||||
// pull me up !
|
||||
}
|
||||
|
||||
provisioner "shell-local" {
|
||||
name = "whipped_york"
|
||||
inline = [ "echo whip_york > ${upper(build.ID)}.${source.name}.txt" ]
|
||||
}
|
||||
provisioner "shell-local" {
|
||||
name = "mascarpone"
|
||||
inline = [ "echo mascarpone >> ${upper(build.ID)}.${source.name}.txt" ]
|
||||
}
|
||||
post-processor "shell-local" {
|
||||
name = "whipped_egg_white"
|
||||
inline = [ "echo whipped_egg_white >> ${upper(build.ID)}.${source.name}.txt" ]
|
||||
}
|
||||
post-processor "shell-local" {
|
||||
name = "dress_with_coffeed_boudoirs"
|
||||
inline = [ "echo dress >> ${upper(build.ID)}.${source.name}.txt" ]
|
||||
}
|
||||
}
|
||||
|
||||
build {
|
||||
name = "recipes"
|
||||
source "source.null.base" {
|
||||
name = "spaghetti_carbonara"
|
||||
}
|
||||
source "source.null.base" {
|
||||
name = "lasagna"
|
||||
}
|
||||
|
||||
provisioner "shell-local" {
|
||||
name = "add_spaghetti"
|
||||
inline = [ "echo spaghetti > ${upper(build.ID)}.${source.name}.txt" ]
|
||||
only = ["null.spaghetti_carbonara"]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
name = "carbonara_it"
|
||||
inline = [ "echo carbonara >> ${upper(build.ID)}.${source.name}.txt" ]
|
||||
except = ["null.lasagna"]
|
||||
}
|
||||
|
||||
|
||||
provisioner "shell-local" {
|
||||
name = "add_lasagna"
|
||||
inline = [ "echo lasagna > ${upper(build.ID)}.${source.name}.txt" ]
|
||||
only = ["null.lasagna"]
|
||||
}
|
||||
|
||||
provisioner "shell-local" {
|
||||
name = "add_tomato"
|
||||
inline = [ "echo tomato >> ${upper(build.ID)}.${source.name}.txt" ]
|
||||
except = ["null.spaghetti_carbonara"]
|
||||
}
|
||||
|
||||
provisioner "shell-local" {
|
||||
name = "add_mozza"
|
||||
inline = [ "echo mozza >> ${upper(build.ID)}.${source.name}.txt" ]
|
||||
except = ["null.spaghetti_carbonara"]
|
||||
}
|
||||
|
||||
post-processor "shell-local" {
|
||||
name = "cook"
|
||||
inline = [ "echo cooking... >> ${upper(build.ID)}.${source.name}.txt" ]
|
||||
except = ["null.spaghetti_carbonara"]
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
source "null" "base" {
|
||||
communicator = "none"
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package hcl2template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// HCL2PostProcessor has a reference to the part of the HCL2 body where it is
|
||||
// defined, allowing to completely reconfigure the PostProcessor right before
|
||||
// calling PostProcess: with contextual variables.
|
||||
// This permits using "${build.ID}" values for example.
|
||||
type HCL2PostProcessor struct {
|
||||
PostProcessor packer.PostProcessor
|
||||
postProcessorBlock *PostProcessorBlock
|
||||
evalContext *hcl.EvalContext
|
||||
builderVariables map[string]string
|
||||
}
|
||||
|
||||
func (p *HCL2PostProcessor) ConfigSpec() hcldec.ObjectSpec {
|
||||
return p.PostProcessor.ConfigSpec()
|
||||
}
|
||||
|
||||
func (p *HCL2PostProcessor) HCL2Prepare(buildVars map[string]interface{}) error {
|
||||
var diags hcl.Diagnostics
|
||||
ectx := p.evalContext
|
||||
if len(buildVars) > 0 {
|
||||
ectx = p.evalContext.NewChild()
|
||||
buildValues := map[string]cty.Value{}
|
||||
for k, v := range buildVars {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
buildValues[k] = cty.StringVal(v)
|
||||
default:
|
||||
return fmt.Errorf("unhandled buildvar type: %T", v)
|
||||
}
|
||||
}
|
||||
ectx.Variables = map[string]cty.Value{
|
||||
buildAccessor: cty.ObjectVal(buildValues),
|
||||
}
|
||||
}
|
||||
|
||||
flatPostProcessorCfg, moreDiags := decodeHCL2Spec(p.postProcessorBlock.HCL2Ref.Rest, ectx, p.PostProcessor)
|
||||
diags = append(diags, moreDiags...)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
return p.PostProcessor.Configure(p.builderVariables, flatPostProcessorCfg)
|
||||
}
|
||||
|
||||
func (p *HCL2PostProcessor) Configure(args ...interface{}) error {
|
||||
return p.PostProcessor.Configure(args...)
|
||||
}
|
||||
|
||||
func (p *HCL2PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
|
||||
generatedData := make(map[string]interface{})
|
||||
if artifactStateData, ok := artifact.State("generated_data").(map[interface{}]interface{}); ok {
|
||||
for k, v := range artifactStateData {
|
||||
generatedData[k.(string)] = v
|
||||
}
|
||||
}
|
||||
|
||||
err := p.HCL2Prepare(generatedData)
|
||||
if err != nil {
|
||||
return nil, false, false, err
|
||||
}
|
||||
return p.PostProcessor.PostProcess(ctx, ui, artifact)
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package hcl2template
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
"github.com/hashicorp/hcl/v2/hcldec"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// HCL2Provisioner has a reference to the part of the HCL2 body where it is
|
||||
// defined, allowing to completely reconfigure the Provisioner right before
|
||||
// calling Provision: with contextual variables.
|
||||
// This permits using "${build.ID}" values for example.
|
||||
type HCL2Provisioner struct {
|
||||
Provisioner packer.Provisioner
|
||||
provisionerBlock *ProvisionerBlock
|
||||
evalContext *hcl.EvalContext
|
||||
builderVariables map[string]string
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) ConfigSpec() hcldec.ObjectSpec {
|
||||
return p.Provisioner.ConfigSpec()
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) HCL2Prepare(buildVars map[string]interface{}) error {
|
||||
var diags hcl.Diagnostics
|
||||
ectx := p.evalContext
|
||||
if len(buildVars) > 0 {
|
||||
ectx = p.evalContext.NewChild()
|
||||
buildValues := map[string]cty.Value{}
|
||||
for k, v := range buildVars {
|
||||
switch v := v.(type) {
|
||||
case string:
|
||||
buildValues[k] = cty.StringVal(v)
|
||||
default:
|
||||
return fmt.Errorf("unhandled buildvar type: %T", v)
|
||||
}
|
||||
}
|
||||
ectx.Variables = map[string]cty.Value{
|
||||
buildAccessor: cty.ObjectVal(buildValues),
|
||||
}
|
||||
}
|
||||
|
||||
flatProvisionerCfg, moreDiags := decodeHCL2Spec(p.provisionerBlock.HCL2Ref.Rest, ectx, p.Provisioner)
|
||||
diags = append(diags, moreDiags...)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
return p.Provisioner.Prepare(p.builderVariables, flatProvisionerCfg)
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) Prepare(args ...interface{}) error {
|
||||
return p.Provisioner.Prepare(args...)
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) Provision(ctx context.Context, ui packer.Ui, c packer.Communicator, vars map[string]interface{}) error {
|
||||
err := p.HCL2Prepare(vars)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.Provisioner.Provision(ctx, ui, c, vars)
|
||||
}
|
||||
@ -0,0 +1,246 @@
|
||||
{
|
||||
"auth": {
|
||||
"oauth2": {
|
||||
"scopes": {
|
||||
"https://www.googleapis.com/auth/plus.me": {
|
||||
"description": "Associate you with your personal info on Google"
|
||||
},
|
||||
"https://www.googleapis.com/auth/userinfo.email": {
|
||||
"description": "View your email address"
|
||||
},
|
||||
"https://www.googleapis.com/auth/userinfo.profile": {
|
||||
"description": "See your personal info, including any personal info you've made publicly available"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"basePath": "/",
|
||||
"baseUrl": "https://www.googleapis.com/",
|
||||
"batchPath": "batch/oauth2/v2",
|
||||
"description": "Obtains end-user authorization grants for use with other Google APIs.",
|
||||
"discoveryVersion": "v1",
|
||||
"documentationLink": "https://developers.google.com/accounts/docs/OAuth2",
|
||||
"etag": "\"u9GIe6H63LSGq-9_t39K2Zx_EAc/zG8qVEU9Oex8Y_g8HrcHwAALOOo\"",
|
||||
"icons": {
|
||||
"x16": "https://www.gstatic.com/images/branding/product/1x/googleg_16dp.png",
|
||||
"x32": "https://www.gstatic.com/images/branding/product/1x/googleg_32dp.png"
|
||||
},
|
||||
"id": "oauth2:v2",
|
||||
"kind": "discovery#restDescription",
|
||||
"methods": {
|
||||
"tokeninfo": {
|
||||
"httpMethod": "POST",
|
||||
"id": "oauth2.tokeninfo",
|
||||
"parameters": {
|
||||
"access_token": {
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"id_token": {
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"token_handle": {
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"path": "oauth2/v2/tokeninfo",
|
||||
"response": {
|
||||
"$ref": "Tokeninfo"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "oauth2",
|
||||
"ownerDomain": "google.com",
|
||||
"ownerName": "Google",
|
||||
"parameters": {
|
||||
"alt": {
|
||||
"default": "json",
|
||||
"description": "Data format for the response.",
|
||||
"enum": [
|
||||
"json"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Responses with Content-Type of application/json"
|
||||
],
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"fields": {
|
||||
"description": "Selector specifying which fields to include in a partial response.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"oauth_token": {
|
||||
"description": "OAuth 2.0 token for the current user.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"prettyPrint": {
|
||||
"default": "true",
|
||||
"description": "Returns response with indentations and line breaks.",
|
||||
"location": "query",
|
||||
"type": "boolean"
|
||||
},
|
||||
"quotaUser": {
|
||||
"description": "An opaque string that represents a user for quota purposes. Must not exceed 40 characters.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"userIp": {
|
||||
"description": "Deprecated. Please use quotaUser instead.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"protocol": "rest",
|
||||
"resources": {
|
||||
"userinfo": {
|
||||
"methods": {
|
||||
"get": {
|
||||
"httpMethod": "GET",
|
||||
"id": "oauth2.userinfo.get",
|
||||
"path": "oauth2/v2/userinfo",
|
||||
"response": {
|
||||
"$ref": "Userinfoplus"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/plus.me",
|
||||
"https://www.googleapis.com/auth/userinfo.email",
|
||||
"https://www.googleapis.com/auth/userinfo.profile"
|
||||
]
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"v2": {
|
||||
"resources": {
|
||||
"me": {
|
||||
"methods": {
|
||||
"get": {
|
||||
"httpMethod": "GET",
|
||||
"id": "oauth2.userinfo.v2.me.get",
|
||||
"path": "userinfo/v2/me",
|
||||
"response": {
|
||||
"$ref": "Userinfoplus"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/plus.me",
|
||||
"https://www.googleapis.com/auth/userinfo.email",
|
||||
"https://www.googleapis.com/auth/userinfo.profile"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"revision": "20200213",
|
||||
"rootUrl": "https://www.googleapis.com/",
|
||||
"schemas": {
|
||||
"Tokeninfo": {
|
||||
"id": "Tokeninfo",
|
||||
"properties": {
|
||||
"access_type": {
|
||||
"description": "The access type granted with this token. It can be offline or online.",
|
||||
"type": "string"
|
||||
},
|
||||
"audience": {
|
||||
"description": "Who is the intended audience for this token. In general the same as issued_to.",
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"description": "The email address of the user. Present only if the email scope is present in the request.",
|
||||
"type": "string"
|
||||
},
|
||||
"expires_in": {
|
||||
"description": "The expiry time of the token, as number of seconds left until expiry.",
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"issued_to": {
|
||||
"description": "To whom was the token issued to. In general the same as audience.",
|
||||
"type": "string"
|
||||
},
|
||||
"scope": {
|
||||
"description": "The space separated list of scopes granted to this token.",
|
||||
"type": "string"
|
||||
},
|
||||
"token_handle": {
|
||||
"description": "The token handle associated with this token.",
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"description": "The obfuscated user id.",
|
||||
"type": "string"
|
||||
},
|
||||
"verified_email": {
|
||||
"description": "Boolean flag which is true if the email address is verified. Present only if the email scope is present in the request.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"Userinfoplus": {
|
||||
"id": "Userinfoplus",
|
||||
"properties": {
|
||||
"email": {
|
||||
"description": "The user's email address.",
|
||||
"type": "string"
|
||||
},
|
||||
"family_name": {
|
||||
"description": "The user's last name.",
|
||||
"type": "string"
|
||||
},
|
||||
"gender": {
|
||||
"description": "The user's gender.",
|
||||
"type": "string"
|
||||
},
|
||||
"given_name": {
|
||||
"description": "The user's first name.",
|
||||
"type": "string"
|
||||
},
|
||||
"hd": {
|
||||
"description": "The hosted domain e.g. example.com if the user is Google apps user.",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "The obfuscated ID of the user.",
|
||||
"type": "string"
|
||||
},
|
||||
"link": {
|
||||
"description": "URL of the profile page.",
|
||||
"type": "string"
|
||||
},
|
||||
"locale": {
|
||||
"description": "The user's preferred locale.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "The user's full name.",
|
||||
"type": "string"
|
||||
},
|
||||
"picture": {
|
||||
"description": "URL of the user's picture image.",
|
||||
"type": "string"
|
||||
},
|
||||
"verified_email": {
|
||||
"default": "true",
|
||||
"description": "Boolean flag which is true if the email address is verified. Always verified because we only return the user's primary email address.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"servicePath": "",
|
||||
"title": "Google OAuth2 API",
|
||||
"version": "v2"
|
||||
}
|
||||
@ -0,0 +1,701 @@
|
||||
// Copyright 2020 Google LLC.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Code generated file. DO NOT EDIT.
|
||||
|
||||
// Package oauth2 provides access to the Google OAuth2 API.
|
||||
//
|
||||
// For product documentation, see: https://developers.google.com/accounts/docs/OAuth2
|
||||
//
|
||||
// Creating a client
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// import "google.golang.org/api/oauth2/v2"
|
||||
// ...
|
||||
// ctx := context.Background()
|
||||
// oauth2Service, err := oauth2.NewService(ctx)
|
||||
//
|
||||
// In this example, Google Application Default Credentials are used for authentication.
|
||||
//
|
||||
// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
|
||||
//
|
||||
// Other authentication options
|
||||
//
|
||||
// By default, all available scopes (see "Constants") are used to authenticate. To restrict scopes, use option.WithScopes:
|
||||
//
|
||||
// oauth2Service, err := oauth2.NewService(ctx, option.WithScopes(oauth2.UserinfoProfileScope))
|
||||
//
|
||||
// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
|
||||
//
|
||||
// oauth2Service, err := oauth2.NewService(ctx, option.WithAPIKey("AIza..."))
|
||||
//
|
||||
// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource:
|
||||
//
|
||||
// config := &oauth2.Config{...}
|
||||
// // ...
|
||||
// token, err := config.Exchange(ctx, ...)
|
||||
// oauth2Service, err := oauth2.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
|
||||
//
|
||||
// See https://godoc.org/google.golang.org/api/option/ for details on options.
|
||||
package oauth2 // import "google.golang.org/api/oauth2/v2"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
googleapi "google.golang.org/api/googleapi"
|
||||
gensupport "google.golang.org/api/internal/gensupport"
|
||||
option "google.golang.org/api/option"
|
||||
internaloption "google.golang.org/api/option/internaloption"
|
||||
htransport "google.golang.org/api/transport/http"
|
||||
)
|
||||
|
||||
// Always reference these packages, just in case the auto-generated code
|
||||
// below doesn't.
|
||||
var _ = bytes.NewBuffer
|
||||
var _ = strconv.Itoa
|
||||
var _ = fmt.Sprintf
|
||||
var _ = json.NewDecoder
|
||||
var _ = io.Copy
|
||||
var _ = url.Parse
|
||||
var _ = gensupport.MarshalJSON
|
||||
var _ = googleapi.Version
|
||||
var _ = errors.New
|
||||
var _ = strings.Replace
|
||||
var _ = context.Canceled
|
||||
var _ = internaloption.WithDefaultEndpoint
|
||||
|
||||
const apiId = "oauth2:v2"
|
||||
const apiName = "oauth2"
|
||||
const apiVersion = "v2"
|
||||
const basePath = "https://www.googleapis.com/"
|
||||
|
||||
// OAuth2 scopes used by this API.
|
||||
const (
|
||||
// Associate you with your personal info on Google
|
||||
PlusMeScope = "https://www.googleapis.com/auth/plus.me"
|
||||
|
||||
// View your email address
|
||||
UserinfoEmailScope = "https://www.googleapis.com/auth/userinfo.email"
|
||||
|
||||
// See your personal info, including any personal info you've made
|
||||
// publicly available
|
||||
UserinfoProfileScope = "https://www.googleapis.com/auth/userinfo.profile"
|
||||
)
|
||||
|
||||
// NewService creates a new Service.
|
||||
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
|
||||
scopesOption := option.WithScopes(
|
||||
"https://www.googleapis.com/auth/plus.me",
|
||||
"https://www.googleapis.com/auth/userinfo.email",
|
||||
"https://www.googleapis.com/auth/userinfo.profile",
|
||||
)
|
||||
// NOTE: prepend, so we don't override user-specified scopes.
|
||||
opts = append([]option.ClientOption{scopesOption}, opts...)
|
||||
opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
|
||||
client, endpoint, err := htransport.NewClient(ctx, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := New(client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if endpoint != "" {
|
||||
s.BasePath = endpoint
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// New creates a new Service. It uses the provided http.Client for requests.
|
||||
//
|
||||
// Deprecated: please use NewService instead.
|
||||
// To provide a custom HTTP client, use option.WithHTTPClient.
|
||||
// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
|
||||
func New(client *http.Client) (*Service, error) {
|
||||
if client == nil {
|
||||
return nil, errors.New("client is nil")
|
||||
}
|
||||
s := &Service{client: client, BasePath: basePath}
|
||||
s.Userinfo = NewUserinfoService(s)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
client *http.Client
|
||||
BasePath string // API endpoint base URL
|
||||
UserAgent string // optional additional User-Agent fragment
|
||||
|
||||
Userinfo *UserinfoService
|
||||
}
|
||||
|
||||
func (s *Service) userAgent() string {
|
||||
if s.UserAgent == "" {
|
||||
return googleapi.UserAgent
|
||||
}
|
||||
return googleapi.UserAgent + " " + s.UserAgent
|
||||
}
|
||||
|
||||
func NewUserinfoService(s *Service) *UserinfoService {
|
||||
rs := &UserinfoService{s: s}
|
||||
rs.V2 = NewUserinfoV2Service(s)
|
||||
return rs
|
||||
}
|
||||
|
||||
type UserinfoService struct {
|
||||
s *Service
|
||||
|
||||
V2 *UserinfoV2Service
|
||||
}
|
||||
|
||||
func NewUserinfoV2Service(s *Service) *UserinfoV2Service {
|
||||
rs := &UserinfoV2Service{s: s}
|
||||
rs.Me = NewUserinfoV2MeService(s)
|
||||
return rs
|
||||
}
|
||||
|
||||
type UserinfoV2Service struct {
|
||||
s *Service
|
||||
|
||||
Me *UserinfoV2MeService
|
||||
}
|
||||
|
||||
func NewUserinfoV2MeService(s *Service) *UserinfoV2MeService {
|
||||
rs := &UserinfoV2MeService{s: s}
|
||||
return rs
|
||||
}
|
||||
|
||||
type UserinfoV2MeService struct {
|
||||
s *Service
|
||||
}
|
||||
|
||||
type Tokeninfo struct {
|
||||
// AccessType: The access type granted with this token. It can be
|
||||
// offline or online.
|
||||
AccessType string `json:"access_type,omitempty"`
|
||||
|
||||
// Audience: Who is the intended audience for this token. In general the
|
||||
// same as issued_to.
|
||||
Audience string `json:"audience,omitempty"`
|
||||
|
||||
// Email: The email address of the user. Present only if the email scope
|
||||
// is present in the request.
|
||||
Email string `json:"email,omitempty"`
|
||||
|
||||
// ExpiresIn: The expiry time of the token, as number of seconds left
|
||||
// until expiry.
|
||||
ExpiresIn int64 `json:"expires_in,omitempty"`
|
||||
|
||||
// IssuedTo: To whom was the token issued to. In general the same as
|
||||
// audience.
|
||||
IssuedTo string `json:"issued_to,omitempty"`
|
||||
|
||||
// Scope: The space separated list of scopes granted to this token.
|
||||
Scope string `json:"scope,omitempty"`
|
||||
|
||||
// TokenHandle: The token handle associated with this token.
|
||||
TokenHandle string `json:"token_handle,omitempty"`
|
||||
|
||||
// UserId: The obfuscated user id.
|
||||
UserId string `json:"user_id,omitempty"`
|
||||
|
||||
// VerifiedEmail: Boolean flag which is true if the email address is
|
||||
// verified. Present only if the email scope is present in the request.
|
||||
VerifiedEmail bool `json:"verified_email,omitempty"`
|
||||
|
||||
// ServerResponse contains the HTTP response code and headers from the
|
||||
// server.
|
||||
googleapi.ServerResponse `json:"-"`
|
||||
|
||||
// ForceSendFields is a list of field names (e.g. "AccessType") to
|
||||
// unconditionally include in API requests. By default, fields with
|
||||
// empty values are omitted from API requests. However, any non-pointer,
|
||||
// non-interface field appearing in ForceSendFields will be sent to the
|
||||
// server regardless of whether the field is empty or not. This may be
|
||||
// used to include empty fields in Patch requests.
|
||||
ForceSendFields []string `json:"-"`
|
||||
|
||||
// NullFields is a list of field names (e.g. "AccessType") to include in
|
||||
// API requests with the JSON null value. By default, fields with empty
|
||||
// values are omitted from API requests. However, any field with an
|
||||
// empty value appearing in NullFields will be sent to the server as
|
||||
// null. It is an error if a field in this list has a non-empty value.
|
||||
// This may be used to include null fields in Patch requests.
|
||||
NullFields []string `json:"-"`
|
||||
}
|
||||
|
||||
func (s *Tokeninfo) MarshalJSON() ([]byte, error) {
|
||||
type NoMethod Tokeninfo
|
||||
raw := NoMethod(*s)
|
||||
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
|
||||
}
|
||||
|
||||
type Userinfoplus struct {
|
||||
// Email: The user's email address.
|
||||
Email string `json:"email,omitempty"`
|
||||
|
||||
// FamilyName: The user's last name.
|
||||
FamilyName string `json:"family_name,omitempty"`
|
||||
|
||||
// Gender: The user's gender.
|
||||
Gender string `json:"gender,omitempty"`
|
||||
|
||||
// GivenName: The user's first name.
|
||||
GivenName string `json:"given_name,omitempty"`
|
||||
|
||||
// Hd: The hosted domain e.g. example.com if the user is Google apps
|
||||
// user.
|
||||
Hd string `json:"hd,omitempty"`
|
||||
|
||||
// Id: The obfuscated ID of the user.
|
||||
Id string `json:"id,omitempty"`
|
||||
|
||||
// Link: URL of the profile page.
|
||||
Link string `json:"link,omitempty"`
|
||||
|
||||
// Locale: The user's preferred locale.
|
||||
Locale string `json:"locale,omitempty"`
|
||||
|
||||
// Name: The user's full name.
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// Picture: URL of the user's picture image.
|
||||
Picture string `json:"picture,omitempty"`
|
||||
|
||||
// VerifiedEmail: Boolean flag which is true if the email address is
|
||||
// verified. Always verified because we only return the user's primary
|
||||
// email address.
|
||||
//
|
||||
// Default: true
|
||||
VerifiedEmail *bool `json:"verified_email,omitempty"`
|
||||
|
||||
// ServerResponse contains the HTTP response code and headers from the
|
||||
// server.
|
||||
googleapi.ServerResponse `json:"-"`
|
||||
|
||||
// ForceSendFields is a list of field names (e.g. "Email") to
|
||||
// unconditionally include in API requests. By default, fields with
|
||||
// empty values are omitted from API requests. However, any non-pointer,
|
||||
// non-interface field appearing in ForceSendFields will be sent to the
|
||||
// server regardless of whether the field is empty or not. This may be
|
||||
// used to include empty fields in Patch requests.
|
||||
ForceSendFields []string `json:"-"`
|
||||
|
||||
// NullFields is a list of field names (e.g. "Email") to include in API
|
||||
// requests with the JSON null value. By default, fields with empty
|
||||
// values are omitted from API requests. However, any field with an
|
||||
// empty value appearing in NullFields will be sent to the server as
|
||||
// null. It is an error if a field in this list has a non-empty value.
|
||||
// This may be used to include null fields in Patch requests.
|
||||
NullFields []string `json:"-"`
|
||||
}
|
||||
|
||||
func (s *Userinfoplus) MarshalJSON() ([]byte, error) {
|
||||
type NoMethod Userinfoplus
|
||||
raw := NoMethod(*s)
|
||||
return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
|
||||
}
|
||||
|
||||
// method id "oauth2.tokeninfo":
|
||||
|
||||
type TokeninfoCall struct {
|
||||
s *Service
|
||||
urlParams_ gensupport.URLParams
|
||||
ctx_ context.Context
|
||||
header_ http.Header
|
||||
}
|
||||
|
||||
// Tokeninfo:
|
||||
func (s *Service) Tokeninfo() *TokeninfoCall {
|
||||
c := &TokeninfoCall{s: s, urlParams_: make(gensupport.URLParams)}
|
||||
return c
|
||||
}
|
||||
|
||||
// AccessToken sets the optional parameter "access_token":
|
||||
func (c *TokeninfoCall) AccessToken(accessToken string) *TokeninfoCall {
|
||||
c.urlParams_.Set("access_token", accessToken)
|
||||
return c
|
||||
}
|
||||
|
||||
// IdToken sets the optional parameter "id_token":
|
||||
func (c *TokeninfoCall) IdToken(idToken string) *TokeninfoCall {
|
||||
c.urlParams_.Set("id_token", idToken)
|
||||
return c
|
||||
}
|
||||
|
||||
// TokenHandle sets the optional parameter "token_handle":
|
||||
func (c *TokeninfoCall) TokenHandle(tokenHandle string) *TokeninfoCall {
|
||||
c.urlParams_.Set("token_handle", tokenHandle)
|
||||
return c
|
||||
}
|
||||
|
||||
// Fields allows partial responses to be retrieved. See
|
||||
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
|
||||
// for more information.
|
||||
func (c *TokeninfoCall) Fields(s ...googleapi.Field) *TokeninfoCall {
|
||||
c.urlParams_.Set("fields", googleapi.CombineFields(s))
|
||||
return c
|
||||
}
|
||||
|
||||
// Context sets the context to be used in this call's Do method. Any
|
||||
// pending HTTP request will be aborted if the provided context is
|
||||
// canceled.
|
||||
func (c *TokeninfoCall) Context(ctx context.Context) *TokeninfoCall {
|
||||
c.ctx_ = ctx
|
||||
return c
|
||||
}
|
||||
|
||||
// Header returns an http.Header that can be modified by the caller to
|
||||
// add HTTP headers to the request.
|
||||
func (c *TokeninfoCall) Header() http.Header {
|
||||
if c.header_ == nil {
|
||||
c.header_ = make(http.Header)
|
||||
}
|
||||
return c.header_
|
||||
}
|
||||
|
||||
func (c *TokeninfoCall) doRequest(alt string) (*http.Response, error) {
|
||||
reqHeaders := make(http.Header)
|
||||
reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200317")
|
||||
for k, v := range c.header_ {
|
||||
reqHeaders[k] = v
|
||||
}
|
||||
reqHeaders.Set("User-Agent", c.s.userAgent())
|
||||
var body io.Reader = nil
|
||||
c.urlParams_.Set("alt", alt)
|
||||
c.urlParams_.Set("prettyPrint", "false")
|
||||
urls := googleapi.ResolveRelative(c.s.BasePath, "oauth2/v2/tokeninfo")
|
||||
urls += "?" + c.urlParams_.Encode()
|
||||
req, err := http.NewRequest("POST", urls, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = reqHeaders
|
||||
return gensupport.SendRequest(c.ctx_, c.s.client, req)
|
||||
}
|
||||
|
||||
// Do executes the "oauth2.tokeninfo" call.
|
||||
// Exactly one of *Tokeninfo or error will be non-nil. Any non-2xx
|
||||
// status code is an error. Response headers are in either
|
||||
// *Tokeninfo.ServerResponse.Header or (if a response was returned at
|
||||
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified
|
||||
// to check whether the returned error was because
|
||||
// http.StatusNotModified was returned.
|
||||
func (c *TokeninfoCall) Do(opts ...googleapi.CallOption) (*Tokeninfo, error) {
|
||||
gensupport.SetOptions(c.urlParams_, opts...)
|
||||
res, err := c.doRequest("json")
|
||||
if res != nil && res.StatusCode == http.StatusNotModified {
|
||||
if res.Body != nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
return nil, &googleapi.Error{
|
||||
Code: res.StatusCode,
|
||||
Header: res.Header,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer googleapi.CloseBody(res)
|
||||
if err := googleapi.CheckResponse(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := &Tokeninfo{
|
||||
ServerResponse: googleapi.ServerResponse{
|
||||
Header: res.Header,
|
||||
HTTPStatusCode: res.StatusCode,
|
||||
},
|
||||
}
|
||||
target := &ret
|
||||
if err := gensupport.DecodeResponse(target, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
// {
|
||||
// "httpMethod": "POST",
|
||||
// "id": "oauth2.tokeninfo",
|
||||
// "parameters": {
|
||||
// "access_token": {
|
||||
// "location": "query",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "id_token": {
|
||||
// "location": "query",
|
||||
// "type": "string"
|
||||
// },
|
||||
// "token_handle": {
|
||||
// "location": "query",
|
||||
// "type": "string"
|
||||
// }
|
||||
// },
|
||||
// "path": "oauth2/v2/tokeninfo",
|
||||
// "response": {
|
||||
// "$ref": "Tokeninfo"
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// method id "oauth2.userinfo.get":
|
||||
|
||||
type UserinfoGetCall struct {
|
||||
s *Service
|
||||
urlParams_ gensupport.URLParams
|
||||
ifNoneMatch_ string
|
||||
ctx_ context.Context
|
||||
header_ http.Header
|
||||
}
|
||||
|
||||
// Get:
|
||||
func (r *UserinfoService) Get() *UserinfoGetCall {
|
||||
c := &UserinfoGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
|
||||
return c
|
||||
}
|
||||
|
||||
// Fields allows partial responses to be retrieved. See
|
||||
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
|
||||
// for more information.
|
||||
func (c *UserinfoGetCall) Fields(s ...googleapi.Field) *UserinfoGetCall {
|
||||
c.urlParams_.Set("fields", googleapi.CombineFields(s))
|
||||
return c
|
||||
}
|
||||
|
||||
// IfNoneMatch sets the optional parameter which makes the operation
|
||||
// fail if the object's ETag matches the given value. This is useful for
|
||||
// getting updates only after the object has changed since the last
|
||||
// request. Use googleapi.IsNotModified to check whether the response
|
||||
// error from Do is the result of In-None-Match.
|
||||
func (c *UserinfoGetCall) IfNoneMatch(entityTag string) *UserinfoGetCall {
|
||||
c.ifNoneMatch_ = entityTag
|
||||
return c
|
||||
}
|
||||
|
||||
// Context sets the context to be used in this call's Do method. Any
|
||||
// pending HTTP request will be aborted if the provided context is
|
||||
// canceled.
|
||||
func (c *UserinfoGetCall) Context(ctx context.Context) *UserinfoGetCall {
|
||||
c.ctx_ = ctx
|
||||
return c
|
||||
}
|
||||
|
||||
// Header returns an http.Header that can be modified by the caller to
|
||||
// add HTTP headers to the request.
|
||||
func (c *UserinfoGetCall) Header() http.Header {
|
||||
if c.header_ == nil {
|
||||
c.header_ = make(http.Header)
|
||||
}
|
||||
return c.header_
|
||||
}
|
||||
|
||||
func (c *UserinfoGetCall) doRequest(alt string) (*http.Response, error) {
|
||||
reqHeaders := make(http.Header)
|
||||
reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200317")
|
||||
for k, v := range c.header_ {
|
||||
reqHeaders[k] = v
|
||||
}
|
||||
reqHeaders.Set("User-Agent", c.s.userAgent())
|
||||
if c.ifNoneMatch_ != "" {
|
||||
reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
|
||||
}
|
||||
var body io.Reader = nil
|
||||
c.urlParams_.Set("alt", alt)
|
||||
c.urlParams_.Set("prettyPrint", "false")
|
||||
urls := googleapi.ResolveRelative(c.s.BasePath, "oauth2/v2/userinfo")
|
||||
urls += "?" + c.urlParams_.Encode()
|
||||
req, err := http.NewRequest("GET", urls, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = reqHeaders
|
||||
return gensupport.SendRequest(c.ctx_, c.s.client, req)
|
||||
}
|
||||
|
||||
// Do executes the "oauth2.userinfo.get" call.
|
||||
// Exactly one of *Userinfoplus or error will be non-nil. Any non-2xx
|
||||
// status code is an error. Response headers are in either
|
||||
// *Userinfoplus.ServerResponse.Header or (if a response was returned at
|
||||
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified
|
||||
// to check whether the returned error was because
|
||||
// http.StatusNotModified was returned.
|
||||
func (c *UserinfoGetCall) Do(opts ...googleapi.CallOption) (*Userinfoplus, error) {
|
||||
gensupport.SetOptions(c.urlParams_, opts...)
|
||||
res, err := c.doRequest("json")
|
||||
if res != nil && res.StatusCode == http.StatusNotModified {
|
||||
if res.Body != nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
return nil, &googleapi.Error{
|
||||
Code: res.StatusCode,
|
||||
Header: res.Header,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer googleapi.CloseBody(res)
|
||||
if err := googleapi.CheckResponse(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := &Userinfoplus{
|
||||
ServerResponse: googleapi.ServerResponse{
|
||||
Header: res.Header,
|
||||
HTTPStatusCode: res.StatusCode,
|
||||
},
|
||||
}
|
||||
target := &ret
|
||||
if err := gensupport.DecodeResponse(target, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
// {
|
||||
// "httpMethod": "GET",
|
||||
// "id": "oauth2.userinfo.get",
|
||||
// "path": "oauth2/v2/userinfo",
|
||||
// "response": {
|
||||
// "$ref": "Userinfoplus"
|
||||
// },
|
||||
// "scopes": [
|
||||
// "https://www.googleapis.com/auth/plus.me",
|
||||
// "https://www.googleapis.com/auth/userinfo.email",
|
||||
// "https://www.googleapis.com/auth/userinfo.profile"
|
||||
// ]
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// method id "oauth2.userinfo.v2.me.get":
|
||||
|
||||
type UserinfoV2MeGetCall struct {
|
||||
s *Service
|
||||
urlParams_ gensupport.URLParams
|
||||
ifNoneMatch_ string
|
||||
ctx_ context.Context
|
||||
header_ http.Header
|
||||
}
|
||||
|
||||
// Get:
|
||||
func (r *UserinfoV2MeService) Get() *UserinfoV2MeGetCall {
|
||||
c := &UserinfoV2MeGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
|
||||
return c
|
||||
}
|
||||
|
||||
// Fields allows partial responses to be retrieved. See
|
||||
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
|
||||
// for more information.
|
||||
func (c *UserinfoV2MeGetCall) Fields(s ...googleapi.Field) *UserinfoV2MeGetCall {
|
||||
c.urlParams_.Set("fields", googleapi.CombineFields(s))
|
||||
return c
|
||||
}
|
||||
|
||||
// IfNoneMatch sets the optional parameter which makes the operation
|
||||
// fail if the object's ETag matches the given value. This is useful for
|
||||
// getting updates only after the object has changed since the last
|
||||
// request. Use googleapi.IsNotModified to check whether the response
|
||||
// error from Do is the result of In-None-Match.
|
||||
func (c *UserinfoV2MeGetCall) IfNoneMatch(entityTag string) *UserinfoV2MeGetCall {
|
||||
c.ifNoneMatch_ = entityTag
|
||||
return c
|
||||
}
|
||||
|
||||
// Context sets the context to be used in this call's Do method. Any
|
||||
// pending HTTP request will be aborted if the provided context is
|
||||
// canceled.
|
||||
func (c *UserinfoV2MeGetCall) Context(ctx context.Context) *UserinfoV2MeGetCall {
|
||||
c.ctx_ = ctx
|
||||
return c
|
||||
}
|
||||
|
||||
// Header returns an http.Header that can be modified by the caller to
|
||||
// add HTTP headers to the request.
|
||||
func (c *UserinfoV2MeGetCall) Header() http.Header {
|
||||
if c.header_ == nil {
|
||||
c.header_ = make(http.Header)
|
||||
}
|
||||
return c.header_
|
||||
}
|
||||
|
||||
func (c *UserinfoV2MeGetCall) doRequest(alt string) (*http.Response, error) {
|
||||
reqHeaders := make(http.Header)
|
||||
reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200317")
|
||||
for k, v := range c.header_ {
|
||||
reqHeaders[k] = v
|
||||
}
|
||||
reqHeaders.Set("User-Agent", c.s.userAgent())
|
||||
if c.ifNoneMatch_ != "" {
|
||||
reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
|
||||
}
|
||||
var body io.Reader = nil
|
||||
c.urlParams_.Set("alt", alt)
|
||||
c.urlParams_.Set("prettyPrint", "false")
|
||||
urls := googleapi.ResolveRelative(c.s.BasePath, "userinfo/v2/me")
|
||||
urls += "?" + c.urlParams_.Encode()
|
||||
req, err := http.NewRequest("GET", urls, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header = reqHeaders
|
||||
return gensupport.SendRequest(c.ctx_, c.s.client, req)
|
||||
}
|
||||
|
||||
// Do executes the "oauth2.userinfo.v2.me.get" call.
|
||||
// Exactly one of *Userinfoplus or error will be non-nil. Any non-2xx
|
||||
// status code is an error. Response headers are in either
|
||||
// *Userinfoplus.ServerResponse.Header or (if a response was returned at
|
||||
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified
|
||||
// to check whether the returned error was because
|
||||
// http.StatusNotModified was returned.
|
||||
func (c *UserinfoV2MeGetCall) Do(opts ...googleapi.CallOption) (*Userinfoplus, error) {
|
||||
gensupport.SetOptions(c.urlParams_, opts...)
|
||||
res, err := c.doRequest("json")
|
||||
if res != nil && res.StatusCode == http.StatusNotModified {
|
||||
if res.Body != nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
return nil, &googleapi.Error{
|
||||
Code: res.StatusCode,
|
||||
Header: res.Header,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer googleapi.CloseBody(res)
|
||||
if err := googleapi.CheckResponse(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := &Userinfoplus{
|
||||
ServerResponse: googleapi.ServerResponse{
|
||||
Header: res.Header,
|
||||
HTTPStatusCode: res.StatusCode,
|
||||
},
|
||||
}
|
||||
target := &ret
|
||||
if err := gensupport.DecodeResponse(target, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
// {
|
||||
// "httpMethod": "GET",
|
||||
// "id": "oauth2.userinfo.v2.me.get",
|
||||
// "path": "userinfo/v2/me",
|
||||
// "response": {
|
||||
// "$ref": "Userinfoplus"
|
||||
// },
|
||||
// "scopes": [
|
||||
// "https://www.googleapis.com/auth/plus.me",
|
||||
// "https://www.googleapis.com/auth/userinfo.email",
|
||||
// "https://www.googleapis.com/auth/userinfo.profile"
|
||||
// ]
|
||||
// }
|
||||
|
||||
}
|
||||
@ -0,0 +1,446 @@
|
||||
{
|
||||
"auth": {
|
||||
"oauth2": {
|
||||
"scopes": {
|
||||
"https://www.googleapis.com/auth/cloud-platform": {
|
||||
"description": "View and manage your data across Google Cloud Platform services"
|
||||
},
|
||||
"https://www.googleapis.com/auth/compute": {
|
||||
"description": "View and manage your Google Compute Engine resources"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"basePath": "",
|
||||
"baseUrl": "https://oslogin.googleapis.com/",
|
||||
"batchPath": "batch",
|
||||
"canonicalName": "Cloud OS Login",
|
||||
"description": "You can use OS Login to manage access to your VM instances using IAM roles.",
|
||||
"discoveryVersion": "v1",
|
||||
"documentationLink": "https://cloud.google.com/compute/docs/oslogin/",
|
||||
"fullyEncodeReservedExpansion": true,
|
||||
"icons": {
|
||||
"x16": "http://www.google.com/images/icons/product/search-16.gif",
|
||||
"x32": "http://www.google.com/images/icons/product/search-32.gif"
|
||||
},
|
||||
"id": "oslogin:v1",
|
||||
"kind": "discovery#restDescription",
|
||||
"mtlsRootUrl": "https://oslogin.mtls.googleapis.com/",
|
||||
"name": "oslogin",
|
||||
"ownerDomain": "google.com",
|
||||
"ownerName": "Google",
|
||||
"parameters": {
|
||||
"$.xgafv": {
|
||||
"description": "V1 error format.",
|
||||
"enum": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"v1 error format",
|
||||
"v2 error format"
|
||||
],
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"access_token": {
|
||||
"description": "OAuth access token.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"alt": {
|
||||
"default": "json",
|
||||
"description": "Data format for response.",
|
||||
"enum": [
|
||||
"json",
|
||||
"media",
|
||||
"proto"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Responses with Content-Type of application/json",
|
||||
"Media download with context-dependent Content-Type",
|
||||
"Responses with Content-Type of application/x-protobuf"
|
||||
],
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"callback": {
|
||||
"description": "JSONP",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"fields": {
|
||||
"description": "Selector specifying which fields to include in a partial response.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"oauth_token": {
|
||||
"description": "OAuth 2.0 token for the current user.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"prettyPrint": {
|
||||
"default": "true",
|
||||
"description": "Returns response with indentations and line breaks.",
|
||||
"location": "query",
|
||||
"type": "boolean"
|
||||
},
|
||||
"quotaUser": {
|
||||
"description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"uploadType": {
|
||||
"description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"upload_protocol": {
|
||||
"description": "Upload protocol for media (e.g. \"raw\", \"multipart\").",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"protocol": "rest",
|
||||
"resources": {
|
||||
"users": {
|
||||
"methods": {
|
||||
"getLoginProfile": {
|
||||
"description": "Retrieves the profile information used for logging in to a virtual machine\non Google Compute Engine.",
|
||||
"flatPath": "v1/users/{usersId}/loginProfile",
|
||||
"httpMethod": "GET",
|
||||
"id": "oslogin.users.getLoginProfile",
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"parameters": {
|
||||
"name": {
|
||||
"description": "Required. The unique ID for the user in format `users/{user}`.",
|
||||
"location": "path",
|
||||
"pattern": "^users/[^/]+$",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"projectId": {
|
||||
"description": "The project ID of the Google Cloud Platform project.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
},
|
||||
"systemId": {
|
||||
"description": "A system ID for filtering the results of the request.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"path": "v1/{+name}/loginProfile",
|
||||
"response": {
|
||||
"$ref": "LoginProfile"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/compute"
|
||||
]
|
||||
},
|
||||
"importSshPublicKey": {
|
||||
"description": "Adds an SSH public key and returns the profile information. Default POSIX\naccount information is set when no username and UID exist as part of the\nlogin profile.",
|
||||
"flatPath": "v1/users/{usersId}:importSshPublicKey",
|
||||
"httpMethod": "POST",
|
||||
"id": "oslogin.users.importSshPublicKey",
|
||||
"parameterOrder": [
|
||||
"parent"
|
||||
],
|
||||
"parameters": {
|
||||
"parent": {
|
||||
"description": "Required. The unique ID for the user in format `users/{user}`.",
|
||||
"location": "path",
|
||||
"pattern": "^users/[^/]+$",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"projectId": {
|
||||
"description": "The project ID of the Google Cloud Platform project.",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"path": "v1/{+parent}:importSshPublicKey",
|
||||
"request": {
|
||||
"$ref": "SshPublicKey"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "ImportSshPublicKeyResponse"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/compute"
|
||||
]
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"projects": {
|
||||
"methods": {
|
||||
"delete": {
|
||||
"description": "Deletes a POSIX account.",
|
||||
"flatPath": "v1/users/{usersId}/projects/{projectsId}",
|
||||
"httpMethod": "DELETE",
|
||||
"id": "oslogin.users.projects.delete",
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"parameters": {
|
||||
"name": {
|
||||
"description": "Required. A reference to the POSIX account to update. POSIX accounts are identified\nby the project ID they are associated with. A reference to the POSIX\naccount is in format `users/{user}/projects/{project}`.",
|
||||
"location": "path",
|
||||
"pattern": "^users/[^/]+/projects/[^/]+$",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"path": "v1/{+name}",
|
||||
"response": {
|
||||
"$ref": "Empty"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/compute"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sshPublicKeys": {
|
||||
"methods": {
|
||||
"delete": {
|
||||
"description": "Deletes an SSH public key.",
|
||||
"flatPath": "v1/users/{usersId}/sshPublicKeys/{sshPublicKeysId}",
|
||||
"httpMethod": "DELETE",
|
||||
"id": "oslogin.users.sshPublicKeys.delete",
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"parameters": {
|
||||
"name": {
|
||||
"description": "Required. The fingerprint of the public key to update. Public keys are identified by\ntheir SHA-256 fingerprint. The fingerprint of the public key is in format\n`users/{user}/sshPublicKeys/{fingerprint}`.",
|
||||
"location": "path",
|
||||
"pattern": "^users/[^/]+/sshPublicKeys/[^/]+$",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"path": "v1/{+name}",
|
||||
"response": {
|
||||
"$ref": "Empty"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/compute"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"description": "Retrieves an SSH public key.",
|
||||
"flatPath": "v1/users/{usersId}/sshPublicKeys/{sshPublicKeysId}",
|
||||
"httpMethod": "GET",
|
||||
"id": "oslogin.users.sshPublicKeys.get",
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"parameters": {
|
||||
"name": {
|
||||
"description": "Required. The fingerprint of the public key to retrieve. Public keys are identified\nby their SHA-256 fingerprint. The fingerprint of the public key is in\nformat `users/{user}/sshPublicKeys/{fingerprint}`.",
|
||||
"location": "path",
|
||||
"pattern": "^users/[^/]+/sshPublicKeys/[^/]+$",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"path": "v1/{+name}",
|
||||
"response": {
|
||||
"$ref": "SshPublicKey"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/compute"
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"description": "Updates an SSH public key and returns the profile information. This method\nsupports patch semantics.",
|
||||
"flatPath": "v1/users/{usersId}/sshPublicKeys/{sshPublicKeysId}",
|
||||
"httpMethod": "PATCH",
|
||||
"id": "oslogin.users.sshPublicKeys.patch",
|
||||
"parameterOrder": [
|
||||
"name"
|
||||
],
|
||||
"parameters": {
|
||||
"name": {
|
||||
"description": "Required. The fingerprint of the public key to update. Public keys are identified by\ntheir SHA-256 fingerprint. The fingerprint of the public key is in format\n`users/{user}/sshPublicKeys/{fingerprint}`.",
|
||||
"location": "path",
|
||||
"pattern": "^users/[^/]+/sshPublicKeys/[^/]+$",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"updateMask": {
|
||||
"description": "Mask to control which fields get updated. Updates all if not present.",
|
||||
"format": "google-fieldmask",
|
||||
"location": "query",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"path": "v1/{+name}",
|
||||
"request": {
|
||||
"$ref": "SshPublicKey"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "SshPublicKey"
|
||||
},
|
||||
"scopes": [
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/compute"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"revision": "20200215",
|
||||
"rootUrl": "https://oslogin.googleapis.com/",
|
||||
"schemas": {
|
||||
"Empty": {
|
||||
"description": "A generic empty message that you can re-use to avoid defining duplicated\nempty messages in your APIs. A typical example is to use it as the request\nor the response type of an API method. For instance:\n\n service Foo {\n rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);\n }\n\nThe JSON representation for `Empty` is empty JSON object `{}`.",
|
||||
"id": "Empty",
|
||||
"properties": {},
|
||||
"type": "object"
|
||||
},
|
||||
"ImportSshPublicKeyResponse": {
|
||||
"description": "A response message for importing an SSH public key.",
|
||||
"id": "ImportSshPublicKeyResponse",
|
||||
"properties": {
|
||||
"loginProfile": {
|
||||
"$ref": "LoginProfile",
|
||||
"description": "The login profile information for the user."
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"LoginProfile": {
|
||||
"description": "The user profile information used for logging in to a virtual machine on\nGoogle Compute Engine.",
|
||||
"id": "LoginProfile",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Required. A unique user ID.",
|
||||
"type": "string"
|
||||
},
|
||||
"posixAccounts": {
|
||||
"description": "The list of POSIX accounts associated with the user.",
|
||||
"items": {
|
||||
"$ref": "PosixAccount"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"sshPublicKeys": {
|
||||
"additionalProperties": {
|
||||
"$ref": "SshPublicKey"
|
||||
},
|
||||
"description": "A map from SSH public key fingerprint to the associated key object.",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"PosixAccount": {
|
||||
"description": "The POSIX account information associated with a Google account.",
|
||||
"id": "PosixAccount",
|
||||
"properties": {
|
||||
"accountId": {
|
||||
"description": "Output only. A POSIX account identifier.",
|
||||
"type": "string"
|
||||
},
|
||||
"gecos": {
|
||||
"description": "The GECOS (user information) entry for this account.",
|
||||
"type": "string"
|
||||
},
|
||||
"gid": {
|
||||
"description": "The default group ID.",
|
||||
"format": "int64",
|
||||
"type": "string"
|
||||
},
|
||||
"homeDirectory": {
|
||||
"description": "The path to the home directory for this account.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Output only. The canonical resource name.",
|
||||
"type": "string"
|
||||
},
|
||||
"operatingSystemType": {
|
||||
"description": "The operating system type where this account applies.",
|
||||
"enum": [
|
||||
"OPERATING_SYSTEM_TYPE_UNSPECIFIED",
|
||||
"LINUX",
|
||||
"WINDOWS"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"The operating system type associated with the user account information is\nunspecified.",
|
||||
"Linux user account information.",
|
||||
"Windows user account information."
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"primary": {
|
||||
"description": "Only one POSIX account can be marked as primary.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"shell": {
|
||||
"description": "The path to the logic shell for this account.",
|
||||
"type": "string"
|
||||
},
|
||||
"systemId": {
|
||||
"description": "System identifier for which account the username or uid applies to.\nBy default, the empty value is used.",
|
||||
"type": "string"
|
||||
},
|
||||
"uid": {
|
||||
"description": "The user ID.",
|
||||
"format": "int64",
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"description": "The username of the POSIX account.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"SshPublicKey": {
|
||||
"description": "The SSH public key information associated with a Google account.",
|
||||
"id": "SshPublicKey",
|
||||
"properties": {
|
||||
"expirationTimeUsec": {
|
||||
"description": "An expiration time in microseconds since epoch.",
|
||||
"format": "int64",
|
||||
"type": "string"
|
||||
},
|
||||
"fingerprint": {
|
||||
"description": "Output only. The SHA-256 fingerprint of the SSH public key.",
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"description": "Public key text in SSH format, defined by\n\u003ca href=\"https://www.ietf.org/rfc/rfc4253.txt\" target=\"_blank\"\u003eRFC4253\u003c/a\u003e\nsection 6.6.",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Output only. The canonical resource name.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"servicePath": "",
|
||||
"title": "Cloud OS Login API",
|
||||
"version": "v1",
|
||||
"version_module": true
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue