func makeSecurityGroupTRList_html(bgcolor string, height string, fontSize string, infoList []*cres.SecurityInfo) string {
	if bgcolor == "" {
		bgcolor = "#FFFFFF"
	}
	if height == "" {
		height = "30"
	}
	if fontSize == "" {
		fontSize = "2"
	}
	strTR := fmt.Sprintf(`
                <tr bgcolor="%s" align="center" height="%s">
                    <td>
                            <font size=%s>$$NUM$$</font>
                    </td>
                    <td>
                            <font size=%s>$$VPCNAME$$</font>
                    </td>
                    <td>
                            <font size=%s>$$SGNAME$$</font>
                    </td>                    
                    <td>
                            <font size=%s>$$SECURITYRULES$$</font>
                    </td>
                    <td>
                            <font size=%s>$$ADDITIONALINFO$$</font>
                    </td>
                    <td>
                        <input type="checkbox" name="check_box" value=$$SGNAME$$>
                    </td>
                </tr>
                `, bgcolor, height, fontSize, fontSize, fontSize, fontSize, fontSize)
	strData := ""
	for i, one := range infoList {
		str := strings.ReplaceAll(strTR, "$$NUM$$", strconv.Itoa(i+1))
		str = strings.ReplaceAll(str, "$$VPCNAME$$", one.VpcIID.NameId)
		str = strings.ReplaceAll(str, "$$SGNAME$$", one.IId.NameId)
		strSRList := ""
		for _, one := range *one.SecurityRules {
			strSRList += "FromPort:" + one.FromPort + ", "
			strSRList += "ToPort:" + one.ToPort + ", "
			strSRList += "IPProtocol:" + one.IPProtocol + ", "
			strSRList += "Direction:" + one.Direction + ", "
			strSRList += "CIDR:" + one.CIDR + ", "
			strSRList += "}<br>"
		}
		str = strings.ReplaceAll(str, "$$SECURITYRULES$$", strSRList)
		strKeyList := ""
		for _, kv := range one.KeyValueList {
			strKeyList += kv.Key + ":" + kv.Value + ", "
		}
		str = strings.ReplaceAll(str, "$$ADDITIONALINFO$$", strKeyList)
		strData += str
	}
	return strData
}
====================================== Security Group
number, VPC Name, SecurityGroup Name, Security Rules, Additional Info, checkbox
package adminweb
import (
	"fmt"
	cr "github.com/cloud-barista/cb-spider/api-runtime/common-runtime"
	cres "github.com/cloud-barista/cb-spider/cloud-control-manager/cloud-driver/interfaces/resources"
	"strconv"
	"encoding/json"
	"net/http"
	"strings"
	"github.com/labstack/echo/v4"
)
func makeVPCTRList_html(bgcolor string, height string, fontSize string, infoList []*cres.VPCInfo) string {
	if bgcolor == "" {
		bgcolor = "#FFFFFF"
	}
	if height == "" {
		height = "30"
	}
	if fontSize == "" {
		fontSize = "2"
	}
	strTR := fmt.Sprintf(`
                <tr bgcolor="%s" align="center" height="%s">
                    <td>
                            <font size=%s>$$NUM$$</font>
                    </td>
                    <td>
                            <font size=%s>$$VPCNAME$$</font>
                    </td>
                    <td>
                            <font size=%s>$$VPCCIDR$$</font>
                    </td>
                    <td>
                            <font size=%s>$$SUBNETINFO$$</font>
                    </td>
                    <td>
                            <font size=%s>$$ADDITIONALINFO$$</font>
                    </td>
                    <td>
                        <input type="checkbox" name="check_box" value=$$VPCNAME$$>
                    </td>
                </tr>
                `, bgcolor, height, fontSize, fontSize, fontSize, fontSize, fontSize)
	strRemoveSubnet := fmt.Sprintf(`
                <a href="javascript:$$REMOVESUBNET$$;">
                        <font size=%s><b>&nbsp;X</b></font>
                </a>
                `, fontSize)
	strAddSubnet := fmt.Sprintf(`
                <textarea style="font-size:12px;text-align:center;" name="subnet_text_box_$$ADDVPC$$" id="subnet_text_box_$$ADDVPC$$" cols=40>{ "Name": "subnet-xx", "IPv4_CIDR": "192.168.xx.xx/24"}</textarea>
                <a href="javascript:$$ADDSUBNET$$;">
                        <font size=%s><b>+</b></font>
                </a>
								`, fontSize)
	strData := ""
	for i, one := range infoList {
		str := strings.ReplaceAll(strTR, "$$NUM$$", strconv.Itoa(i+1))
		str = strings.ReplaceAll(str, "$$VPCNAME$$", one.IId.NameId)
		str = strings.ReplaceAll(str, "$$VPCCIDR$$", one.IPv4_CIDR)
		var vpcName = one.IId.NameId
		strSubnetList := ""
		for _, one := range one.SubnetInfoList {
			strSubnetList += one.IId.NameId + ", "
			strSubnetList += "CIDR:" + one.IPv4_CIDR + ", {"
			for _, kv := range one.KeyValueList {
				strSubnetList += kv.Key + ":" + kv.Value + ", "
			}
			strSubnetList += "}"
			var subnetName = one.IId.NameId
			strSubnetList += strings.ReplaceAll(strRemoveSubnet, "$$REMOVESUBNET$$", "deleteSubnet('"+vpcName+"', '"+subnetName+"')")
			strSubnetList += "<br>"
		}
		vpcAddSubnet := strings.ReplaceAll(strAddSubnet, "$$ADDVPC$$", vpcName)
		strSubnetList += strings.ReplaceAll(vpcAddSubnet, "$$ADDSUBNET$$", "postSubnet('"+vpcName+"')")
		str = strings.ReplaceAll(str, "$$SUBNETINFO$$", strSubnetList)
		strKeyList := ""
		for _, kv := range one.KeyValueList {
			strKeyList += kv.Key + ":" + kv.Value + ", "
		}
		str = strings.ReplaceAll(str, "$$ADDITIONALINFO$$", strKeyList)
		strData += str
	}
	return strData
}
func makePostVPCFunc_js() string {
	strFunc := `
                function postVPC() {
                        var connConfig = parent.frames["top_frame"].document.getElementById("connConfig").innerHTML;
                        var textboxes = document.getElementsByName('text_box');
            sendJson = '{ "ConnectionName" : "' + connConfig + '", "ReqInfo" : { "Name" : "$$VPCNAME$$", "IPv4_CIDR" : "$$VPCCIDR$$", "SubnetInfoList" : $$SUBNETINFOLIST$$ }}'
                        for (var i = 0; i < textboxes.length; i++) {  
                                switch (textboxes[i].id) {
                                        case "1":
                                                sendJson = sendJson.replace("$$VPCNAME$$", textboxes[i].value);
                                                break;
                                        case "2":
                                                sendJson = sendJson.replace("$$VPCCIDR$$", textboxes[i].value);
                                                break;
                                        case "3":
                                                sendJson = sendJson.replace("$$SUBNETINFOLIST$$", textboxes[i].value);
                                                break;
                                        default:
                                                break;
                                }
                        }
                        var xhr = new XMLHttpRequest();
                        xhr.open("POST", "$$SPIDER_SERVER$$/spider/vpc", false);
                        xhr.setRequestHeader('Content-Type', 'application/json');
                        xhr.send(sendJson);
			location.reload();
                }
        `
	strFunc = strings.ReplaceAll(strFunc, "$$SPIDER_SERVER$$", "http://"+cr.ServiceIPorName+cr.ServicePort)  
	return strFunc
}
func makePostSubnetFunc_js() string {
	strFunc := `
                function postSubnet(vpcName) {
                        var connConfig = parent.frames["top_frame"].document.getElementById("connConfig").innerHTML;
                        var textbox = document.getElementById('subnet_text_box_' + vpcName);
                        sendJson = '{ "ConnectionName" : "' + connConfig + '", "ReqInfo" :  $$SUBNETINFO$$ }'
                        sendJson = sendJson.replace("$$SUBNETINFO$$", textbox.value);
                        var xhr = new XMLHttpRequest();
                        xhr.open("POST", "$$SPIDER_SERVER$$/spider/vpc/" + vpcName + "/subnet", false);
                        xhr.setRequestHeader('Content-Type', 'application/json');
                        xhr.send(sendJson);
                        location.reload();
                }
        `
	strFunc = strings.ReplaceAll(strFunc, "$$SPIDER_SERVER$$", "http://"+cr.ServiceIPorName+cr.ServicePort)  
	return strFunc
}
func makeDeleteVPCFunc_js() string {
	strFunc := `
                function deleteVPC() {
                        var connConfig = parent.frames["top_frame"].document.getElementById("connConfig").innerHTML;
                        var checkboxes = document.getElementsByName('check_box');
                        for (var i = 0; i < checkboxes.length; i++) {  
                                if (checkboxes[i].checked) {
                                        var xhr = new XMLHttpRequest();
                                        xhr.open("DELETE", "$$SPIDER_SERVER$$/spider/vpc/" + checkboxes[i].value, false);
                                        xhr.setRequestHeader('Content-Type', 'application/json');
					sendJson = '{ "ConnectionName": "' + connConfig + '"}'
                                        xhr.send(sendJson);
                                }
                        }
			location.reload();
                }
        `
	strFunc = strings.ReplaceAll(strFunc, "$$SPIDER_SERVER$$", "http://"+cr.ServiceIPorName+cr.ServicePort)  
	return strFunc
}
func makeDeleteSubnetFunc_js() string {
	strFunc := `
                function deleteSubnet(vpcName, subnetName) {
                        var connConfig = parent.frames["top_frame"].document.getElementById("connConfig").innerHTML;
                        var xhr = new XMLHttpRequest();
                        xhr.open("DELETE", "$$SPIDER_SERVER$$/spider/vpc/" + vpcName + "/subnet/" + subnetName, false);
                        xhr.setRequestHeader('Content-Type', 'application/json');
                        sendJson = '{ "ConnectionName": "' + connConfig + '"}'
                        xhr.send(sendJson);
                        location.reload();
                }
        `
	strFunc = strings.ReplaceAll(strFunc, "$$SPIDER_SERVER$$", "http://"+cr.ServiceIPorName+cr.ServicePort)  
	return strFunc
}
func VPC(c echo.Context) error {
	cblog.Info("call VPC()")
	connConfig := c.Param("ConnectConfig")
	if connConfig == "region not set" {
		htmlStr := `
			<html>
			<head>
			    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
			    <script type="text/javascript">
				alert(connConfig)
			    </script>
			</head>
			<body>
				<br>
				<br>
				<label style="font-size:24px;color:#606262;">&nbsp;&nbsp;&nbsp;Please select a Connection Configuration! (MENU: 2.CONNECTION)</label>	
			</body>
		`
		return c.HTML(http.StatusOK, htmlStr)
	}
	htmlStr := `
                <html>
                <head>
                    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
                    <script type="text/javascript">
                `
	htmlStr += makeCheckBoxToggleFunc_js()
	htmlStr += makePostVPCFunc_js()
	htmlStr += makeDeleteVPCFunc_js()
	htmlStr += makePostSubnetFunc_js()
	htmlStr += makeDeleteSubnetFunc_js()
	htmlStr += `
                    </script>
                </head>
                <body>
                    <table border="0" bordercolordark="#F8F8FF" cellpadding="0" cellspacing="1" bgcolor="#FFFFFF"  style="font-size:small;">
                `
	htmlStr += makeActionTR_html("6", "", "deleteVPC()", "2")
	nameWidthList := []NameWidth{
		{"VPC Name", "200"},
		{"VPC CIDR", "200"},
		{"Subnet Info", "300"},
		{"Additional Info", "300"},
	}
	htmlStr += makeTitleTRList_html("#DDDDDD", "2", nameWidthList, true)
	resBody, err := getResourceList_with_Connection_JsonByte(connConfig, "vpc")
	if err != nil {
		cblog.Error(err)
		return echo.NewHTTPError(http.StatusInternalServerError, err.Error())
	}
	var info struct {
		ResultList []*cres.VPCInfo `json:"vpc"`
	}
	json.Unmarshal(resBody, &info)
	htmlStr += makeVPCTRList_html("", "", "", info.ResultList)
	htmlStr += `
                        <tr bgcolor="#FFFFFF" align="center" height="30">
                            <td>
                                    <font size=2>#</font>
                            </td>
                            <td>
                                <input style="font-size:12px;text-align:center;" type="text" name="text_box" id="1" value="vpc-01">
                            </td>
                            <td>
                                <input style="font-size:12px;text-align:center;" type="text" name="text_box" id="2" value="192.168.0.0/16">
                            </td>
                            <td>
                                <textarea style="font-size:12px;text-align:center;" name="text_box" id="3" cols=50>[ { "Name": "subnet-01", "IPv4_CIDR": "192.168.1.0/24"} ]</textarea>
                            </td>
                            <td>
                                <input style="font-size:12px;text-align:center;" type="text" name="text_box" id="4" disabled value="N/A">
                            </td>                            
                            <td>
                                <a href="javascript:postVPC()">
                                    <font size=3><b>+</b></font>
                                </a>
                            </td>
                        </tr>
                `
	htmlStr += `
                    </table>
		    <hr>
                </body>
                </html>
        `
	return c.HTML(http.StatusOK, htmlStr)
}