diff --git a/firstapp/samples/gophercloud/getting_started.go b/firstapp/samples/gophercloud/getting_started.go index 6dcf30fdf..daf16dd48 100644 --- a/firstapp/samples/gophercloud/getting_started.go +++ b/firstapp/samples/gophercloud/getting_started.go @@ -1,294 +1,310 @@ package main import ( - "fmt" - "io/ioutil" - - "github.com/rackspace/gophercloud" - "github.com/rackspace/gophercloud/openstack" - "github.com/rackspace/gophercloud/openstack/compute/v2/flavors" - "github.com/rackspace/gophercloud/openstack/compute/v2/images" - "github.com/rackspace/gophercloud/openstack/compute/v2/servers" - "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip" - "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs" - "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups" - "github.com/rackspace/gophercloud/openstack/networking/v2/networks" - "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external" + "fmt" + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack" + "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips" + "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs" + "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups" + "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors" + "github.com/gophercloud/gophercloud/openstack/compute/v2/images" + "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" + "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external" + "github.com/gophercloud/gophercloud/openstack/networking/v2/networks" + "io/ioutil" + "os" ) func main() { - // step-1 - var authUsername string = "your_auth_username" - var authPassword string = "your_auth_password" - var authUrl string = "http://controller:5000" - var projectName string = "your_project_id" - var regionName string = "your_region_name" - authOpts := gophercloud.AuthOptions{ - IdentityEndpoint: authUrl, - Username: authUsername, - Password: authPassword, - TenantID: projectName, - } - provider, _ := openstack.AuthenticatedClient(authOpts) - client, _ := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{ - Region: regionName, - }) + // step-1 + authOpts, err := openstack.AuthOptionsFromEnv() + if err != nil { + fmt.Println(err) + return + } - // step-2 - pager := images.ListDetail(client, images.ListOpts{}) - page, _ := pager.AllPages() - imageList, _ := images.ExtractImages(page) - fmt.Println(imageList) + provider, err := openstack.AuthenticatedClient(authOpts) + if err != nil { + fmt.Println(err) + return + } - // step-3 - pager = flavors.ListDetail(client, flavors.ListOpts{}) - page, _ = pager.AllPages() - flavorList, _ := flavors.ExtractFlavors(page) - fmt.Println(flavorList) + var regionName = os.Getenv("OS_REGION_NAME") + client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{ + Region: regionName, + Type: "computev21", + }) + if err != nil { + fmt.Println(err) + return + } - // step-4 - imageID := "74e6d1ec-9a08-444c-8518-4f232446386d" - image, _ := images.Get(client, imageID).Extract() - fmt.Println(image) + // step-2 + pager := images.ListDetail(client, images.ListOpts{}) + page, _ := pager.AllPages() + imageList, _ := images.ExtractImages(page) + fmt.Println(imageList) - // step-5 - flavorID := "1" - flavor, _ := flavors.Get(client, flavorID).Extract() - fmt.Println(flavor) + // step-3 + pager = flavors.ListDetail(client, flavors.ListOpts{}) + page, _ = pager.AllPages() + flavorList, _ := flavors.ExtractFlavors(page) + fmt.Println(flavorList) - // step-6 - instanceName := "testing" - testingInstance, _ := servers.Create(client, servers.CreateOpts{ - Name: instanceName, - ImageRef: imageID, - FlavorRef: flavorID, - }).Extract() - fmt.Println(testingInstance) + // step-4 + imageID := "74e6d1ec-9a08-444c-8518-4f232446386d" + image, _ := images.Get(client, imageID).Extract() + fmt.Println(image) - // step-7 - pager = servers.List(client, servers.ListOpts{}) - page, _ = pager.AllPages() - serverList, _ := servers.ExtractServers(page) - fmt.Println(serverList) + // step-5 + flavorID := "1" + flavor, _ := flavors.Get(client, flavorID).Extract() + fmt.Println(flavor) - // step-8 - servers.Delete(client, testingInstance.ID) + // step-6 + instanceName := "testing" + testingInstance, err := servers.Create(client, servers.CreateOpts{ + Name: instanceName, + ImageRef: imageID, + FlavorRef: flavorID, + }).Extract() + if err != nil { + fmt.Println(err) + return + } + fmt.Println(testingInstance) - // step-9 - fmt.Println("Checking for existing SSH key pair...") - keyPairName := "demokey" - pubKeyFile := "~/.ssh/id_rsa.pub" - keyPairExists := false + // step-7 + pager = servers.List(client, servers.ListOpts{}) + page, _ = pager.AllPages() + serverList, _ := servers.ExtractServers(page) + fmt.Println(serverList) - pager = keypairs.List(client) - page, _ = pager.AllPages() - keypairList, _ := keypairs.ExtractKeyPairs(page) - for _, k := range keypairList { - if k.Name == keyPairName { - keyPairExists = true - break - } - } + // step-8 + servers.Delete(client, testingInstance.ID) - if keyPairExists { - fmt.Println("Keypair " + keyPairName + " already exists. Skipping import.") - } else { - fmt.Println("adding keypair...") - bs, _ := ioutil.ReadFile(pubKeyFile) - keypairs.Create(client, keypairs.CreateOpts{ - Name: keyPairName, - PublicKey: string(bs), - }).Extract() - } + // step-9 + fmt.Println("Checking for existing SSH key pair...") + keyPairName := "demokey" + pubKeyFile := "~/.ssh/id_rsa.pub" + keyPairExists := false - pager = keypairs.List(client) - page, _ = pager.AllPages() - keypairList, _ = keypairs.ExtractKeyPairs(page) - fmt.Println(keypairList) + pager = keypairs.List(client) + page, _ = pager.AllPages() + keypairList, _ := keypairs.ExtractKeyPairs(page) + for _, k := range keypairList { + if k.Name == keyPairName { + keyPairExists = true + break + } + } - // step-10 - fmt.Println("Checking for existing security group...") - var allInOneSecurityGroup secgroups.SecurityGroup - securityGroupName := "all-in-one" - securityGroupExists := false + if keyPairExists { + fmt.Println("Keypair " + keyPairName + " already exists. Skipping import.") + } else { + fmt.Println("adding keypair...") + bs, _ := ioutil.ReadFile(pubKeyFile) + keypairs.Create(client, keypairs.CreateOpts{ + Name: keyPairName, + PublicKey: string(bs), + }).Extract() + } - pager = secgroups.List(client) - page, _ = pager.AllPages() - secgroupList, _ := secgroups.ExtractSecurityGroups(page) - for _, secGroup := range secgroupList { - if secGroup.Name == securityGroupName { - allInOneSecurityGroup = secGroup - securityGroupExists = true - break - } - } + pager = keypairs.List(client) + page, _ = pager.AllPages() + keypairList, _ = keypairs.ExtractKeyPairs(page) + fmt.Println(keypairList) - if securityGroupExists { - fmt.Println("Security Group " + allInOneSecurityGroup.Name + " already exists. Skipping creation.") - } else { - allInOneSecurityGroup, _ := secgroups.Create(client, secgroups.CreateOpts{ - Name: securityGroupName, - Description: "network access for all-in-one application.", - }).Extract() - secgroups.CreateRule(client, secgroups.CreateRuleOpts{ - ParentGroupID: allInOneSecurityGroup.ID, - FromPort: 80, - ToPort: 80, - IPProtocol: "TCP", - CIDR: "0.0.0.0/0", - }).Extract() - secgroups.CreateRule(client, secgroups.CreateRuleOpts{ - ParentGroupID: allInOneSecurityGroup.ID, - FromPort: 22, - ToPort: 22, - IPProtocol: "TCP", - CIDR: "0.0.0.0/0", - }).Extract() - } + // step-10 + fmt.Println("Checking for existing security group...") + var allInOneSecurityGroup secgroups.SecurityGroup + securityGroupName := "all-in-one" + securityGroupExists := false - pager = secgroups.List(client) - page, _ = pager.AllPages() - secgroupList, _ = secgroups.ExtractSecurityGroups(page) - fmt.Println(secgroupList) + pager = secgroups.List(client) + page, _ = pager.AllPages() + secgroupList, _ := secgroups.ExtractSecurityGroups(page) + for _, secGroup := range secgroupList { + if secGroup.Name == securityGroupName { + allInOneSecurityGroup = secGroup + securityGroupExists = true + break + } + } - // step-11 - userData := `#!/usr/bin/env bash -curl -L -s https://git.openstack.org/cgit/openstack/faafo/plain/contrib/install.sh | bash -s -- \ - -i faafo -i messaging -r api -r worker -r demo -` + if securityGroupExists { + fmt.Println("Security Group " + allInOneSecurityGroup.Name + " already exists. Skipping creation.") + } else { + allInOneSecurityGroup, _ := secgroups.Create(client, secgroups.CreateOpts{ + Name: securityGroupName, + Description: "network access for all-in-one application.", + }).Extract() + secgroups.CreateRule(client, secgroups.CreateRuleOpts{ + ParentGroupID: allInOneSecurityGroup.ID, + FromPort: 80, + ToPort: 80, + IPProtocol: "TCP", + CIDR: "0.0.0.0/0", + }).Extract() + secgroups.CreateRule(client, secgroups.CreateRuleOpts{ + ParentGroupID: allInOneSecurityGroup.ID, + FromPort: 22, + ToPort: 22, + IPProtocol: "TCP", + CIDR: "0.0.0.0/0", + }).Extract() + } - // step-12 - fmt.Println("Checking for existing instance...") - instanceName = "all-in-one" - instanceExists := false + pager = secgroups.List(client) + page, _ = pager.AllPages() + secgroupList, _ = secgroups.ExtractSecurityGroups(page) + fmt.Println(secgroupList) - pager = servers.List(client, servers.ListOpts{}) - page, _ = pager.AllPages() - serverList, _ = servers.ExtractServers(page) - for _, s := range serverList { - if s.Name == instanceName { - testingInstance = &s - instanceExists = true - break - } - } + // step-11 + userData := `#!/usr/bin/env bash + curl -L -s https://git.openstack.org/cgit/openstack/faafo/plain/contrib/install.sh | bash -s -- \ + -i faafo -i messaging -r api -r worker -r demo` - if instanceExists { - fmt.Println("Instance " + testingInstance.Name + " already exists. Skipping creation.") - } else { - opts := servers.CreateOpts{ - Name: instanceName, - ImageRef: image.ID, - FlavorRef: flavor.ID, - SecurityGroups: []string{securityGroupName}, - UserData: []byte(userData), - } - testingInstance, _ = servers.Create(client, keypairs.CreateOptsExt{ - CreateOptsBuilder: opts, - KeyName: keyPairName, - }).Extract() - } - servers.WaitForStatus(client, testingInstance.ID, "ACTIVE", 300) + // step-12 + fmt.Println("Checking for existing instance...") + instanceName = "all-in-one" + instanceExists := false - pager = servers.List(client, servers.ListOpts{}) - page, _ = pager.AllPages() - serverList, _ = servers.ExtractServers(page) - fmt.Println(serverList) + pager = servers.List(client, servers.ListOpts{}) + page, _ = pager.AllPages() + serverList, _ = servers.ExtractServers(page) + for _, s := range serverList { + if s.Name == instanceName { + testingInstance = &s + instanceExists = true + break + } + } - // step-13 - var privateIP string - for t, addrs := range testingInstance.Addresses { - if t != "private" || len(privateIP) != 0 { - continue - } - addrs, ok := addrs.([]interface{}) - if !ok { - continue - } - for _, addr := range addrs { - a, ok := addr.(map[string]interface{}) - if !ok || a["version"].(float64) != 4 { - continue - } - ip, ok := a["addr"].(string) - if ok && len(ip) != 0 { - privateIP = ip - fmt.Println("Private IP found: " + privateIP) - break - } - } - } + if instanceExists { + fmt.Println("Instance " + testingInstance.Name + " already exists. Skipping creation.") + } else { + opts := servers.CreateOpts{ + Name: instanceName, + ImageRef: image.ID, + FlavorRef: flavor.ID, + SecurityGroups: []string{securityGroupName}, + UserData: []byte(userData), + } + testingInstance, err = servers.Create(client, keypairs.CreateOptsExt{ + CreateOptsBuilder: opts, + KeyName: keyPairName, + }).Extract() + if err != nil { + fmt.Println(err) + return + } + } + servers.WaitForStatus(client, testingInstance.ID, "ACTIVE", 300) - // step-14 - var publicIP string - for t, addrs := range testingInstance.Addresses { - if t != "public" || len(publicIP) != 0 { - continue - } - addrs, ok := addrs.([]interface{}) - if !ok { - continue - } - for _, addr := range addrs { - a, ok := addr.(map[string]interface{}) - if !ok || a["version"].(float64) != 4 { - continue - } - ip, ok := a["addr"].(string) - if ok && len(ip) != 0 { - publicIP = ip - fmt.Println("Public IP found: " + publicIP) - break - } - } - } + pager = servers.List(client, servers.ListOpts{}) + page, _ = pager.AllPages() + serverList, _ = servers.ExtractServers(page) + fmt.Println(serverList) - // step-15 - fmt.Println("Checking for unused Floating IP...") - var unusedFloatingIP string - pager = floatingip.List(client) - page, _ = pager.AllPages() - floatingIPList, _ := floatingip.ExtractFloatingIPs(page) - for _, ip := range floatingIPList { - if ip.InstanceID == "" { - unusedFloatingIP = ip.IP - break - } - } + // step-13 + var privateIP string + for t, addrs := range testingInstance.Addresses { + if t != "private" || len(privateIP) != 0 { + continue + } + addrs, ok := addrs.([]interface{}) + if !ok { + continue + } + for _, addr := range addrs { + a, ok := addr.(map[string]interface{}) + if !ok || a["version"].(float64) != 4 { + continue + } + ip, ok := a["addr"].(string) + if ok && len(ip) != 0 { + privateIP = ip + fmt.Println("Private IP found: " + privateIP) + break + } + } + } - networkClient, _ := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ - Region: regionName, - }) + // step-14 + var publicIP string + for t, addrs := range testingInstance.Addresses { + if t != "public" || len(publicIP) != 0 { + continue + } + addrs, ok := addrs.([]interface{}) + if !ok { + continue + } + for _, addr := range addrs { + a, ok := addr.(map[string]interface{}) + if !ok || a["version"].(float64) != 4 { + continue + } + ip, ok := a["addr"].(string) + if ok && len(ip) != 0 { + publicIP = ip + fmt.Println("Public IP found: " + publicIP) + break + } + } + } - pager = networks.List(networkClient, networks.ListOpts{}) - page, _ = pager.AllPages() - poolList, _ := external.ExtractList(page) - for _, pool := range poolList { - if len(unusedFloatingIP) != 0 || !pool.External { - continue - } - fmt.Println("Allocating new Floating IP from pool: " + pool.Name) - f, _ := floatingip.Create(client, floatingip.CreateOpts{Pool: pool.Name}).Extract() - unusedFloatingIP = f.IP - } + // step-15 + fmt.Println("Checking for unused Floating IP...") + var unusedFloatingIP string + pager = floatingips.List(client) + page, _ = pager.AllPages() + floatingIPList, _ := floatingips.ExtractFloatingIPs(page) + for _, ip := range floatingIPList { + if ip.InstanceID == "" { + unusedFloatingIP = ip.IP + break + } + } - // step-16 - if len(publicIP) != 0 { - fmt.Println("Instance " + testingInstance.Name + " already has a public ip. Skipping attachment.") - } else { - floatingip.Associate(client, testingInstance.ID, unusedFloatingIP) - } + networkClient, _ := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{ + Region: regionName, + }) - // step-17 - var actualIPAddress string - if len(publicIP) != 0 { - actualIPAddress = publicIP - } else if len(unusedFloatingIP) != 0 { - actualIPAddress = unusedFloatingIP - } else { - actualIPAddress = privateIP - } + pager = networks.List(networkClient, networks.ListOpts{}) + page, _ = pager.AllPages() + poolList, _ := external.ExtractList(page) + for _, pool := range poolList { + if len(unusedFloatingIP) != 0 || !pool.External { + continue + } + fmt.Println("Allocating new Floating IP from pool: " + pool.Name) + f, _ := floatingips.Create(client, floatingips.CreateOpts{Pool: pool.Name}).Extract() + unusedFloatingIP = f.IP + } - fmt.Println("The Fractals app will be deployed to http://" + actualIPAddress) + // step-16 + if len(publicIP) != 0 { + fmt.Println("Instance " + testingInstance.Name + " already has a public ip. Skipping attachment.") + } else { + opts := floatingips.AssociateOpts{ + FloatingIP: unusedFloatingIP, + } + floatingips.AssociateInstance(client, testingInstance.ID, opts) + } + + // step-17 + var actualIPAddress string + if len(publicIP) != 0 { + actualIPAddress = publicIP + } else if len(unusedFloatingIP) != 0 { + actualIPAddress = unusedFloatingIP + } else { + actualIPAddress = privateIP + } + + fmt.Println("The Fractals app will be deployed to http://" + actualIPAddress) } diff --git a/firstapp/source/appendix.rst b/firstapp/source/appendix.rst index 5b5b37fa7..e7a671578 100644 --- a/firstapp/source/appendix.rst +++ b/firstapp/source/appendix.rst @@ -33,3 +33,24 @@ Specify a network during instance build image=image_id, flavor=flavor_id, network=network_id) + +.. only:: gophercloud + + Add the option Networks and send its id to attach the instance to: + + .. code-block:: go + + opts := servers.CreateOpts { + Name: instanceName, + ImageRef: image.ID, + FlavorRef: flavor.ID, + SecurityGroups: []string{securityGroupName}, + UserData: []byte(userData), + Networks: []servers.Network{servers.Network{UUID: networkID}}, + + } + + testingInstance, _ = servers.Create(client, keypairs.CreateOptsExt { + CreateOptsBuilder: opts, + KeyName: keyPairName, + }).Extract() diff --git a/firstapp/source/getting_started.rst b/firstapp/source/getting_started.rst index 169c2955c..56121dd3e 100644 --- a/firstapp/source/getting_started.rst +++ b/firstapp/source/getting_started.rst @@ -97,9 +97,9 @@ and toolkits with the OpenStack cloud: Use it to write C++ or C# code for Microsoft applications. - https://www.nuget.org/packages/openstack.net * - Go - - `gophercloud `_ + - `gophercloud `_ - A go-based SDK. - Use it with multiple clouds. + Use it to write Golang code that works with OpenStack clouds. - http://gophercloud.io/ For a list of available SDKs, see `Software Development Kits `_. @@ -232,7 +232,7 @@ To interact with the cloud, you must also have .. only:: gophercloud - `a recent version of gophercloud installed `_ + `a recent version of gophercloud installed `_ Obtain the following information from your cloud provider: @@ -383,14 +383,14 @@ to run code snippets in your language of choice. .. only:: gophercloud - To try it, add the following code to go file + Use environment variables to set your cloud credentials .. literalinclude:: ../samples/gophercloud/getting_started.go :language: go :start-after: step-1 :end-before: step-2 - .. note:: The client object accesses the Compute v2.0 service, + .. note:: The client object accesses the Compute v2.0 service and type v2.1, so that version is in this tutorial. Flavors and images