Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature subnet #156

Closed
wants to merge 12 commits into from
Closed

Feature subnet #156

wants to merge 12 commits into from

Conversation

minsikl
Copy link
Contributor

@minsikl minsikl commented Jun 20, 2017

softlayer_subnet resource supports portable subnet and static subnet management.
softlayer_subnet.md, resource_softlayer_subnet.go, and resource_softlayer_subnet_test.go files are added to implement softlayer_subnet resource. This PR will solve the issue #147

@minsikl minsikl requested a review from renier June 20, 2017 02:46
```hcl
# Create a new portable subnet
resource "softlayer_subnet" "portable_subnet" {
type = "Portable"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there can only be two types, portable or static, make it a boolean then portable = true or static = true to avoid possible spelling errors. If it is not portable, then it is static and vice-versa.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SoftLayer internally uses some subnet types: PRIMARY, ADDITIONAL_PRIMARY, SECONDARY, ROUTED_TO_VLAN, SECONDARY_ON_VLAN, STORAGE_NETWORK, and STATIC_IP_ROUTED. From an end user perspective, the types can be simplified to: Primary, Static, Portable, and Global. We can ignore Global type because softlayer_global_ip is already provided. As of now, softlayer_subnet only supports Static and Portable because Primary subnet cannot be ordered manually. However, I think that Primary subnet ordering will be supported in the future. Then, we can extend this resource without schema update.

softlayer_subnet data source also can be added later. Unlike softlayer_subnet resource, the data source may supports Primary, Portable, Static. In this case, we can use the same attribute name type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@minsikl ok, in that case, why not use the same type strings as the SL API? What would static map to? STATIC_IP_ROUTED? What about portable?

The point is, if we can't make it fool-proof with booleans because there could be more than two types, then let's go with the raw API type names and then we can point there for the list of allowed types and spelling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@renier The initial code used ROUTED_TO_VLAN for portable subnets and STATIC_IP_ROUTED for static subnets. The subnet type can be retrieved using SoftLayer_Network_Subnet ::subnetType. However, I realized that SL API returns additional types such as SECONDARY_ON_VLAN, SUBNET_ON_VLAN, and STATIC_IP_ROUTED. After IPv6 feature is added, I got additional types such as STATIC_IP6_ROUTED. The raw subnet type is not an input parameter of a create function and I'm not able to guess which type will be returned from SL API. In end-user perspective, these raw types are meaningless and SL Portal uses terminology Portable, Static.

Copy link
Contributor

@renier renier Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we go with the portal or with the API? is the question.

If we go with the portal names, it would be good to at least document what that means in API types.

The raw subnet type is not an input parameter of a create function and I'm not able to guess which type will be returned from SL API.

What kinds of subnets can you create then? and how do you specify the kind upon creation? (over the API)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, the user could just provide the required resource attribute without specifying the type,

I explained that primary subnet and portable subnet has the same attributes. How will you distinguish the primary subnet if you don't have type attribute?

primary = true/false

primary = true is okay. But, what is primary = false? Is that mean that the subnet will be global, secondary, third, or portable? Will you add an attribute per types such as static = true and secondary = true? primary is one of subnet types. If you use type attribute, you don't have to add additional true/false attributes to support different types. Why do you use true/false for type names?

Copy link
Contributor

@renier renier Jun 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, the user could just provide the required resource attribute without specifying the type,

I explained that primary subnet and portable subnet has the same attributes. How will you distinguish the primary subnet if you don't have type attribute?

Can a user order a primary subnet today? If not, then I stand by that we should not add a required pseudo-attribute based on something that has not happened in the API yet. We don't have enough information on how to handle until it actually does. Does this make sense?

Is it that we know that orderable primary subnets is in the works and we expect that to be available any moment now? If so, do we know exactly how the ordering of a primary subnet will look like?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@renier softlayer_vlan already provides a function to create the first primary subnet. When you create a new VLAN using terraform, you should define the size of the first primary subnet. Then, placeOrder in softlayer_vlan resource sends priceId of VLAN and priceId of the primary subnet and creates a new VLAN with a primary subnet. So, primary subnets ordering requires same information with portable subnets ordering.

Subnet types are not pseudo-attributes. price item key names contain them, SL portal, automatic tickets, and knowledgelayer use them. Only SL API provides it's internal subnet types.

Boolean attributes should be only used when SL API provides boolean properties or the attributes are optional values such as advanced monitering or redundant power supply. Or they will be pseudo-attributes, and it's hard to understand the meaning.

I defined a general softlayer_subnet resource and it is a pseudo resource. That's why the type attribute is important in softlayer_subnet resource. type is added to define a real resource type of subnets. In the later, if a new attribute is added to describe a new subnet type such as primary=true/false, primary and type will provide duplicated information, and I don't think that it is a good design. Current softlayer_subnet only supports parts of SL subnet types. At least, we need to provide extensible schema if we want to use softlayer_subnet.

If you don't want to use type attribute, let's just define separate resources softlayer_portable_subnet and softlayer_static_subnet. There is no advantage to using softlayer_subnet and if softlayer_subnet is provided without type, it will just make confusion.

Copy link
Contributor

@renier renier Jun 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

softlayer_vlan already provides a function to create the first primary subnet.

That's good to know and understand. I had not made the link between the vlan and the primary subnet. Why were you thinking that primary could be an additional type to softlayer_subnet, when it is already being provided by softlayer_vlan?

Subnet types are not pseudo-attributes. price item key names contain them, SL portal, automatic tickets, and knowledgelayer use them. Only SL API provides it's internal subnet types.
Boolean attributes should be only used when SL API provides boolean properties or the attributes are optional values such as advanced monitering or redundant power supply. Or they will be pseudo-attributes, and it's hard to understand the meaning.

In this case, the type is an attribute that is not synced with the API and is only managed locally. Thus, it is a pseudo-attribute of the resource by definition. Just as any boolean flags in other resources that are also only managed locally. The most common pseudo-attributes are booleans, because you usually don't need to make those kinds of attributes more complex and should not if possible.

I defined a general softlayer_subnet resource and it is a pseudo resource.

Based on my definition above, a pseudo-resource would be something that is not sync-ed with the cloud and it would be managed completely locally. For example, the random provider in terraform only has pseudo-resources. It follows that softlayer_subnet is not a pseudo-resource.

If you don't want to use type attribute, let's just define separate resources softlayer_portable_subnet and softlayer_static_subnet. There is no advantage to using softlayer_subnet and if softlayer_subnet is provided without type, it will just make confusion.

It doesn't have to be confusing if we document that portable subnets are created when you fill out the vlan_id, otherwise if you provide the endpoint_ip, it is static. Even less if you provide a documented computed attribute to the resource computing this fact for them as a word (portable or static).

Creating multiple resources, one per subnet type, is also an option, as long as 99% of the code is shared among them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's good to know and understand.

I gave you the primary subnet provisioning example as an answer to your question: Can a user order a primary subnet today? If not, then I stand by that we should not add a required pseudo-attribute based on something that has not happened in the API yet. We don't have enough information on how to handle until it actually does.. You can see that primary subnet requires same attributes with portable subnet when you create a new primary subnet.

Why were you thinking that primary could be an additional type to softlayer_subnet, when it is already being provided by softlayer_vlan?

If you get a chance to deploy middle/large size systems or some cluster solutions on SoftLayer, you will find several primary subnet requirements which are not provided in SoftLayer. You can only create the first primary subnet as I explained above. You are not able to create 2nd/3rd primary subnets with a specific CIDR. Some cluster solutions require specific CIDR and some users want to reserve primary subnets in their VLAN for their firewall rules or applications.

Based on my definition above, a pseudo-resource would be something that is not sync-ed with the cloud and it would be managed completely locally. For example, the random provider in terraform only has pseudo-resources. It follows that softlayer_subnet is not a pseudo-resource.

primary subnet, portable subnet, static subnet, and global subnet are combinations of interface and routing commands on physical routers and switches. subnet is a general network terminology which provides IP range and CIDR information. But, primary subnet, portable subnet, static subnet, and global subnet are not general terminologies and only used in SoftLayer. They are offering names and you can create and manage them on SoftLayer. subnet is used to refer to these soft layer offerings, not the actual resource name.

It doesn't have to be confusing if we document that portable subnets are created when you fill out the vlan_id, otherwise if you provide the endpoint_ip, it is static. Even less if you provide a documented computed attribute to the resource computing this fact for them as a word (portable or static).

Documents must, of course, be provided. Nevertheless, if there is a better way to define a resource, that method should be used.
Indirect resource definition methods also affect tf file readability. In a tf file where dozens of subnets are defined, people have to extract the subnet type by identifying the manual, deducing the subnet type, or creating a separate script.

Creating multiple resources, one per subnet type, is also an option, as long as 99% of the code is shared among them.

I'll create create two different subnets softlayer_subnet_portable and softlayer_subnet_static.

# Create a new portable subnet
resource "softlayer_subnet" "portable_subnet" {
type = "Portable"
network = "PRIVATE"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with the type of network. if there can only be two types, public and private, then make it a boolean private = true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},

// IP version 4 or IP version 6
"ip_version": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we have a default of 4 for the ip version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},

// Provides IP address/netmask format (ex. 10.10.10.10/28)
"subnet": &schema.Schema{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to validate the format here? Also, the resource is called subnet, so having a property also called the same can mislead the user. Can we calle it cidr or cidr_mask?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subnet is a computed attribute. So, validation is not necessary. In SoftLayer Portal, that column name is subnet and VLAN resource uses subnet as an attribute name of IP address/cidr format. I can change the attribute name to more user-friendly name. I think that cidr can be used as a name of this attribute. But, SoftLayer API uses this field name to represent cidr block(ex. /25). How about ip_cidr or ip_address_cidr?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. If it is computed and SoftLayer portal calls it subnet, how about subnet_cidr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

virtual_guest, bare_metal, lb_vpx, and vlan uses the name subnet or public/private_sunbet for this cidr notation. For consistency, I would like to use the name subnet. However subnet_cidr is also good.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should somehow say it is a cidr in the property. Explaining it as "a subnet resource has a subnet property" is going to be a problem. For the other resources, that problem does not exist. Consistency with the other resources does not seem to be necessary for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

d.Set("subnet", *subnet.NetworkIdentifier+"/"+strconv.Itoa(*subnet.Cidr))
if subnet.Note != nil {
d.Set("notes", *subnet.Note)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary, but these blocks could be refactored with d.Set("notes", sl.Get(subnet.Note, nil))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

d.Set("type", "Static")
} else if strings.Contains(*subnet.SubnetType, "VLAN") {
d.Set("type", "Portable")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@minsikl There are SubnetTypes that would not contain STATIC or VLAN. In that case "type" would be unset. Is that intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@renier Portable subnets contain "VLAN" and Static subnets contain "STATIC". In the future, additional types can be added. For example, Primary subnets contain "PRIMARY".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@minsikl Since there are some types that do not contain either word, technically, would it would be possible to get that from the API? If so, programmatically, it would be safer to add an else clause to handle that situation. For example, to throw an error in that case, since we don't support any other type of subnet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@renier Users may try to import different type of subnets. The current code will not generate an error. If you want to check the type strictly, you can throw an exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the code to generate an error when an invalid subnet type is detected.

@minsikl minsikl closed this Jul 17, 2017
@minsikl minsikl deleted the feature-subnet branch July 17, 2017 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants