Issues with creating multiple vm's with Terraform for Azure - virtual-machine

I am having issues with creating multiple virtual machines in Azure using Terraform. While creating the network interfaces I run into an error regarding the creation of the public ip address id:
I assume that I am using the count function incorrectly, or need a different approach entirely.
Code:
provider "azurerm" {
version = "~>2.0"
features {}
subscription_id = "XXXX"
client_id = "XXXX"
client_secret = "XXXX"
tenant_id = "XXXX"
}
resource "azurerm_resource_group" "rg" {
name = "${var.prefix}test_project"
location = var.location
tags = var.tags
}
resource "azurerm_virtual_network" "vnet" {
name = "${var.prefix}Vnet"
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = azurerm_resource_group.rg.name
tags = var.tags
}
resource "azurerm_subnet" "subnet" {
name = "${var.prefix}Subnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefix = "10.0.1.0/24"
}
resource "azurerm_public_ip" "publicip" {
name = "${var.prefix}PublicIP${count.index}"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
allocation_method = "Dynamic"
tags = var.tags
count = 2
}
resource "azurerm_network_security_group" "nsg" {
name = "${var.prefix}NetworkSecurityGroup"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
tags = var.tags
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_network_interface" "nic" {
name = "${var.prefix}NIC${count.index}"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
tags = var.tags
count = 2
ip_configuration {
name = "${var.prefix}NICConfig${count.index}"
subnet_id = azurerm_subnet.subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = ["${element(azurerm_public_ip.publicip.id, count.index)}"]
}
}
resource "azurerm_network_interface_security_group_association" "example" {
count = length(azurerm_network_interface.nic)
network_interface_id = "${azurerm_network_interface.nic[count.index]}"
network_security_group_id = azurerm_network_security_group.nsg.id
}
resource "azurerm_linux_virtual_machine" "vm" {
count = 2
name = "${var.prefix}VM${count.index}"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
network_interface_ids = azurerm_network_interface.nic[count.index]
size = "Standard_DS1_v2"
tags = var.tags
os_disk {
name = "${var.prefix}OsDisk${count.index}"
caching = "ReadWrite"
storage_account_type = "Premium_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = lookup(var.sku, var.location)
version = "latest"
}
computer_name = "${var.computer_name}-${count.index}"
admin_username = var.admin_username
admin_password = var.admin_password
disable_password_authentication = false
}
Can anyone help me resolve this issue??

I'm pretty sure all you need to do is change
public_ip_address_id = ["${element(azurerm_public_ip.publicip.id, count.index)}"]
to
public_ip_address_id = ["${azurerm_public_ip.publicip[count.index].id}"]
In general, references like azurerm_public_ip.publicip.id work for singular resources (i.e. those that don't use count). So the use of element is kind of assuming a singular resource. As soon as count is used, resources start behaving like lists and need to be treated as such.

Related

Terraform Conditional Content Block Inside Resource

How do I make ip_configuration optional to turn the below:
resource "azurerm_firewall" "example" {
name = "testfirewall"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
ip_configuration {
name = "configuration"
subnet_id = azurerm_subnet.example.id
public_ip_address_id = azurerm_public_ip.example.id
}
}
In to something that OPTIONALLY accepts values in this:
variable "ip_configuration" {
type = object({
name = string // Specifies the name of the IP Configuration.
subnet_id = string // Reference to the subnet associated with the IP Configuration.
public_ip_address_id = string // The ID of the Public IP Address associated with the firewall.
})
description = "(Optional) An ip_configuration block as documented"
default = null
}
I was looking at dynamic blocks, lookups and try expressions but nothing seems to work. Can anyone help? I have spent days on it trying to figure it out
Edit:
There maybe a neater way to do it, but I have found something that works. If someone can improve on this that would be great, but thanks for those who have replied.
subnet_id should only appear in the first ip_configuration which is why I have decided to use the numbering system on the key.
resource "azurerm_firewall" "example" {
name = "testfirewall"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
dynamic "ip_configuration" {
for_each = var.ip_configuration
iterator = ip
content {
name = ip.value["name"]
subnet_id = ip.key == "0" ? ip.value["subnet_id"] : null
public_ip_address_id = ip.value["public_ip_address_id"]
}
}
}
variable "ip_configuration" {
type = map
description = <<-EOT
(Optional) An ip_configuration block is nested maps with 0, 1, 2, 3 as the name of the map as documented below:
name = string // Specifies the name of the IP Configuration.
public_ip_address_id = string // The ID of the Public IP Address associated with the firewall.
subnet_id = string // Reference to the subnet associated with the IP Configuration. The Subnet used for the Firewall must have the name AzureFirewallSubnet and the subnet mask must be at least a /26.
NOTE: Only the first map (with a key of 0) should have a subnet_id property.
EXAMPLE LAYOUT:
{
"0" = {
name = "first_pip_configuration"
public_ip_address_id = azurerm_public_ip.firstpip.id
subnet_id = azurerm_subnet.example.id
},
"1" = {
name = "second_pip_configuration"
public_ip_address_id = azurerm_public_ip.secondpip.id
},
"2" = {
name = "third_pip_configuration"
public_ip_address_id = azurerm_public_ip.thirdpip.id
}
}
EOT
default = {}
}
There maybe a neater way to do it, but I have found something that works. If someone can improve on this that would be great, but thanks for those who have replied.
subnet_id should only appear in the first ip_configuration which is why I have decided to use the numbering system on the key.
resource "azurerm_firewall" "example" {
name = "testfirewall"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
dynamic "ip_configuration" {
for_each = var.ip_configuration
iterator = ip
content {
name = ip.value["name"]
subnet_id = ip.key == "0" ? ip.value["subnet_id"] : null
public_ip_address_id = ip.value["public_ip_address_id"]
}
}
}
variable "ip_configuration" {
type = map
description = <<-EOT
(Optional) An ip_configuration block is nested maps with 0, 1, 2, 3 as the name of the map as documented below:
name = string // Specifies the name of the IP Configuration.
public_ip_address_id = string // The ID of the Public IP Address associated with the firewall.
subnet_id = string // Reference to the subnet associated with the IP Configuration. The Subnet used for the Firewall must have the name AzureFirewallSubnet and the subnet mask must be at least a /26.
NOTE: Only the first map (with a key of 0) should have a subnet_id property.
EXAMPLE LAYOUT:
{
"0" = {
name = "first_pip_configuration"
public_ip_address_id = azurerm_public_ip.firstpip.id
subnet_id = azurerm_subnet.example.id
},
"1" = {
name = "second_pip_configuration"
public_ip_address_id = azurerm_public_ip.secondpip.id
},
"2" = {
name = "third_pip_configuration"
public_ip_address_id = azurerm_public_ip.thirdpip.id
}
}
EOT
default = {}
}

How to duplicate line on itself?

In a JetBrains editor, what is the shortcut (or trick) to duplicate a line on itself without breakline (not like Ctrl + D). In other words, I want to turn this:
constructor(obj: Schema$Car) {
this.brand =
this.id =
this.model =
this.photoBack =
this.photoFront =
this.photoInteriorBack =
this.photoInteriorFront =
this.photoSide =
this.seatCount =
this.year =
}
into this:
constructor(obj: Schema$Car) {
this.brand = obj.brand
this.id = obj.id
this.model = obj.model
this.photoBack = obj.photoBack
this.photoFront = obj.photoFront
this.photoInteriorBack = obj.photoInteriorFront
this.photoInteriorFront = obj.photoInteriorFront
this.photoSide = obj.photoSide
this.seatCount = obj.seatCount
this.year = obj.year
}

Using Terraform to add Storage Virtual Network Rule

Is there a way to add a Virtual Network Rule to a storage account like there is with Azure SQL? There is the azurerm_sql_virtual_network_rule but there does not appear to be an equivalent for storage accounts.
Here is a sample of Usage with Network Rules, you could refer to it.
resource "azurerm_resource_group" "testrg" {
name = "resourceGroupName"
location = "westus"
}
resource "azurerm_virtual_network" "test" {
name = "virtnetname"
address_space = ["10.0.0.0/16"]
location = "${azurerm_resource_group.testrg.location}"
resource_group_name = "${azurerm_resource_group.testrg.name}"
}
resource "azurerm_subnet" "test" {
name = "subnetname"
resource_group_name = "${azurerm_resource_group.testrg.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.0.2.0/24"
service_endpoints = ["Microsoft.Sql","Microsoft.Storage"]
}
resource "azurerm_storage_account" "testsa" {
name = "storageaccountname"
resource_group_name = "${azurerm_resource_group.testrg.name}"
location = "${azurerm_resource_group.testrg.location}"
account_tier = "Standard"
account_replication_type = "LRS"
network_rules {
ip_rules = ["127.0.0.1"]
virtual_network_subnet_ids = ["${azurerm_subnet.test.id}"]
}
tags {
environment = "staging"
}
}

How to get Rates from UPS Rate API?

I am using nopcommerce 3.5. I have added plugin of UPS of TransitInTime and Rate API. I want to get rates by calling UPS Rate API. I want all Rates in dropdown on page load.
So for the first I am using test application using webservices of RateWebReference and in which I get only one Rate but I want Rates for all shipping option.
Here is my code of RateWSClient.cs
RateService rate = new RateService();
RateRequest rateRequest = new RateRequest();
UPSSecurity upss = new UPSSecurity();
UPSSecurityServiceAccessToken upssSvcAccessToken = new UPSSecurityServiceAccessToken();
upssSvcAccessToken.AccessLicenseNumber = "CC....";
upss.ServiceAccessToken = upssSvcAccessToken;
UPSSecurityUsernameToken upssUsrNameToken = new UPSSecurityUsernameToken();
upssUsrNameToken.Username = "gi..";
upssUsrNameToken.Password = "Ch..";
upss.UsernameToken = upssUsrNameToken;
rate.UPSSecurityValue = upss;
RequestType request = new RequestType();
String[] requestOption = { "Rate" };
request.RequestOption = requestOption;
rateRequest.Request = request;
ShipmentType shipment = new ShipmentType();
ShipperType shipper = new ShipperType();
shipper.ShipperNumber = "A65V88";
RateWSSample.RateWebReference1.AddressType shipperAddress = new RateWSSample.RateWebReference1.AddressType();
String[] addressLine = { "", "", "" };
shipperAddress.AddressLine = addressLine;
shipperAddress.City = "";
shipperAddress.PostalCode = "30076";
shipperAddress.StateProvinceCode = "GA";
shipperAddress.CountryCode = "US";
shipperAddress.AddressLine = addressLine;
shipper.Address = shipperAddress;
shipment.Shipper = shipper;
ShipFromType shipFrom = new ShipFromType();
RateWSSample.RateWebReference1.AddressType shipFromAddress = new RateWSSample.RateWebReference1.AddressType();
shipFromAddress.AddressLine = addressLine;
shipFromAddress.City = "";
shipFromAddress.PostalCode = "30076";
shipFromAddress.StateProvinceCode = "GA";
shipFromAddress.CountryCode = "US";
shipFrom.Address = shipFromAddress;
shipment.ShipFrom = shipFrom;
ShipToType shipTo = new ShipToType();
ShipToAddressType shipToAddress = new ShipToAddressType();
String[] addressLine1 = { "", "", "" };
shipToAddress.AddressLine = addressLine1;
shipToAddress.City = "";
shipToAddress.PostalCode = "92262";
shipToAddress.StateProvinceCode = "";
shipToAddress.CountryCode = "US";
shipTo.Address = shipToAddress;
shipment.ShipTo = shipTo;
CodeDescriptionType service = new CodeDescriptionType();
//Below code uses dummy date for reference. Please udpate as required.
service.Code = "02";
shipment.Service = service;
PackageType package = new PackageType();
PackageWeightType packageWeight = new PackageWeightType();
packageWeight.Weight = "125";
CodeDescriptionType uom = new CodeDescriptionType();
uom.Code = "LBS";
uom.Description = "pounds";
packageWeight.UnitOfMeasurement = uom;
package.PackageWeight = packageWeight;
CodeDescriptionType packType = new CodeDescriptionType();
packType.Code = "02";
package.PackagingType = packType;
PackageType[] pkgArray = { package };
shipment.Package = pkgArray;
//Shipping Rate Chart
// ShipmentRatingOptionsType SRO = new ShipmentRatingOptionsType();
//SRO.RateChartIndicator = "";
//shipment.ShipmentRatingOptions= SRO;
//rateRequest.Shipment = shipment;
ShipmentRatingOptionsType SRO = new ShipmentRatingOptionsType();
SRO.NegotiatedRatesIndicator = "";
shipment.ShipmentRatingOptions = SRO;
rateRequest.Shipment = shipment;
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
Console.WriteLine(rateRequest);
RateResponse rateResponse = rate.ProcessRate(rateRequest);
Console.WriteLine("The transaction was a " + rateResponse.Response.ResponseStatus.Description);
Console.WriteLine("Total Shipment Charges " + rateResponse.RatedShipment[0].TotalCharges.MonetaryValue + rateResponse.RatedShipment[0].TotalCharges.CurrencyCode);
Console.ReadKey();
I have resolved this questions. So If you face this kind of problem don't forget to use
String[] requestOption = { "Shop" };
in place of
String[] requestOption = { "Rate" };
Then you will get rates for all shipping options.

i had upload file and some field items to document library i have made one field mandatory in that field but even then i am able to upload file

SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(SPContext.Current.Web.Url, SPUserToken.SystemAccount))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPFolder folder = web.Folders["ContractorDetails"];
SPFileCollection filecol = folder.Files;
Boolean replaceExistingFiles = true;
string filename = System.IO.Path.GetFileName(FileUpload.PostedFile.FileName);
byte[] contents = new byte[Convert.ToInt32(FileUpload.PostedFile.ContentLength)];
SPFile addedFile = filecol.Add(filename, contents, replaceExistingFiles);
SPItem newItem = addedFile.Item;
newItem["Title"] = ddlTitle.SelectedValue;
newItem["First Name"] = tbFirstName.Text;
newItem["Middle Name"] = tbMiddleName.Text;
newItem["Last Name"] = tbLastName.Text;
newItem["NT User Name"] = tbNtuser.Text;
newItem["Contract Firm"] = tbContractFirm.Text;
newItem["Employee Type"] = tbEmpType.Text;
newItem["Division"] = ddlDivision.SelectedValue;
newItem["Location"] = ddlLocation.SelectedValue;
newItem["Contract Start Date"] = dateTimeStart.SelectedDate;
newItem["Contract End Date"] = dateTimeEnd.SelectedDate;
newItem["Project Term"] = Convert.ToInt32(tbProjectTerm.Text);
// newItem["Manager"] = PeopleEditor1.t
newItem["Comments"] = tbcomments.Text;
newItem.Update();
addedFile.Update();
web.AllowUnsafeUpdates = false;
}
}
});
}
Can you just try to upload file from UI to check field is mandatory or not?