[GCP] 入門1

GCPを使ってる企業が相当増えてる印象
AzureもMicrosoft系で開発してる企業は使っているがGCPほど広がっていない印象
むしろ、GCPを使えないと時代遅れになりそう

ということで、GCPを学ぶことにした。

### GCPの特徴
– Googleが運営
– Big Queryが優秀らしい
– App Engineは自動スケール
– Machine Learningも先行している

Google Cloud Shellで操作をする
Google Compute Engine (GCE) が、AWSでいうEC2
なるほど、GCEから始めたい

[Terraform 0.14.6] S3を作る

$ terraform –version
Terraform v0.14.6
$ mkdir terraform
$ cd ~
.aws/credentials

[default]
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

main.tf

provider "aws" {
  profile    = "default"
  region     = "ap-northeast-1"
}

resource "aws_instance" "example" {
    ami = "ami-*"
    instance_type = "t2.micro"
}

$ terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# aws_instance.example will be created
+ resource “aws_instance” “example” {
+ ami = “ami-*”
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
+ cpu_core_count = (known after apply)
+ cpu_threads_per_core = (known after apply)
+ get_password_data = false
+ host_id = (known after apply)
+ id = (known after apply)
+ instance_state = (known after apply)
+ instance_type = “t2.micro”
+ ipv6_address_count = (known after apply)
+ ipv6_addresses = (known after apply)
+ key_name = (known after apply)
+ outpost_arn = (known after apply)
+ password_data = (known after apply)
+ placement_group = (known after apply)
+ primary_network_interface_id = (known after apply)
+ private_dns = (known after apply)
+ private_ip = (known after apply)
+ public_dns = (known after apply)
+ public_ip = (known after apply)
+ secondary_private_ips = (known after apply)
+ security_groups = (known after apply)
+ source_dest_check = true
+ subnet_id = (known after apply)
+ tenancy = (known after apply)
+ vpc_security_group_ids = (known after apply)

+ ebs_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ snapshot_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}

+ enclave_options {
+ enabled = (known after apply)
}

+ ephemeral_block_device {
+ device_name = (known after apply)
+ no_device = (known after apply)
+ virtual_name = (known after apply)
}

+ metadata_options {
+ http_endpoint = (known after apply)
+ http_put_response_hop_limit = (known after apply)
+ http_tokens = (known after apply)
}

+ network_interface {
+ delete_on_termination = (known after apply)
+ device_index = (known after apply)
+ network_interface_id = (known after apply)
}

+ root_block_device {
+ delete_on_termination = (known after apply)
+ device_name = (known after apply)
+ encrypted = (known after apply)
+ iops = (known after apply)
+ kms_key_id = (known after apply)
+ tags = (known after apply)
+ throughput = (known after apply)
+ volume_id = (known after apply)
+ volume_size = (known after apply)
+ volume_type = (known after apply)
}
}

Plan: 1 to add, 0 to change, 0 to destroy.

————————————————————————

Note: You didn’t specify an “-out” parameter to save this plan, so Terraform
can’t guarantee that exactly these actions will be performed if
“terraform apply” is subsequently run.

$ terraform apply
Error: Error launching source instance: MissingInput: No subnets found for the default VPC ‘vpc-*’. Please specify a subnet.

ちょっとvpcに問題があるので、S3にする

provider "aws" {
  profile    = "default"
  region     = "ap-northeast-1"
}

resource "aws_s3_bucket" "b" {
  bucket = "terraform-test-hpscript"
  acl    = "private"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# aws_s3_bucket.b will be created
+ resource “aws_s3_bucket” “b” {
+ acceleration_status = (known after apply)
+ acl = “private”
+ arn = (known after apply)
+ bucket = “terraform-test-hpscript”
+ bucket_domain_name = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags = {
+ “Environment” = “Dev”
+ “Name” = “My bucket”
}
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)

+ versioning {
+ enabled = (known after apply)
+ mfa_delete = (known after apply)
}
}

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
Terraform will perform the actions described above.
Only ‘yes’ will be accepted to approve.

Enter a value: yes

aws_s3_bucket.b: Creating…
aws_s3_bucket.b: Still creating… [10s elapsed]
aws_s3_bucket.b: Creation complete after 11s [id=terraform-test-hpscript]

なるほど、terraformの意味がわかった。確かに便利だわ。

Vagrant Amazon Linux2にTerraformをインストールする

$ TER_VER=`curl -s https://api.github.com/repos/hashicorp/terraform/releases/latest | grep tag_name | cut -d: -f2 | tr -d \”\,\v | awk ‘{$1=$1};1’`
$ echo ${TER_VER}
0.14.6
$ wget https://releases.hashicorp.com/terraform/${TER_VER}/terraform_${TER_VER}_linux_amd64.zip
$ unzip terraform_${TER_VER}_linux_amd64.zip
$ ls
$ sudo mv terraform /usr/local/bin/
$ terraform –version
Terraform v0.14.6

まじかよーーーー
1分で出来たやんか。。。。とりあえず、S3にbucket作成ぐらいはやっておきたい。

[Spring Boot2.4.2] XMLで文字列表示

MainController.java

package com.example.demo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainController {
	public static void main(String[] args) {
		
		ClassPathXmlApplicationContext context =
				new ClassPathXmlApplicationContext("applicationContext.xml");
		
		ISyain syain = context.getBean("testSyain", ISyain.class);
		
		System.out.println(syain.getHello());
		context.close();		
	}
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="testSyain" class="com.example.demo.Syain"></bean>
</beans>

ISyain.java

package com.example.demo;

public interface ISyain {
	public String getHello();
}

Syain.java

package com.example.demo;

public class Syain implements ISyain {
	@Override
	public String getHello() {
		return "Hello World!";
	}
}

なるほどー

[Spring Boot2.4.2] 例外処理

TestException.java

package com.example.demo;

public class TestException extends RuntimeException {
	private static final long serialVersionUID = 1L;
	
	TestException(String msg){
		super(msg);
	}
}

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Check</title>
  </head>
  <body>
    <p th:text="${message1}"></p>
  </body>
</html>

MainController.java

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test1")
public class MainController {

    @GetMapping
	public String index(Model model)  {
	runSample();
	 return "test1/index";
	}
    
    void runSample()   {
		int i = 5;
		if (i == 5) {
			throw new TestException("独自の例外です"); 
		}
	}
}

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Feb 07 16:57:28 JST 2021
There was an unexpected error (type=Internal Server Error, status=500).
独自の例外です
com.example.demo.TestException: 独自の例外です

[Spring Boot2.4.2] Hibernateでselectする

HibernateはRed Hat開発のフリーソフト

pom.xml

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-annotations</artifactId>
			<version>3.5.6-Final</version>
		</dependency>

application.propertiesは変更なし

src/main/java/hibernate-config.java

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 
 <hibernate-configuration>
 
 <session-factory>
    <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
	<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/test</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <property name="hibernate.connection.pool_size">1</property>
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <property name="hibernate.show_sql">true</property>
 </session-factory>
 </hibernate-configuration>

Syain.java

package com.example.demo;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;

@Entity
@Table(name="syain")
public class Syain {
	@Id
	private Integer id;
	private String name;
	private String romaji;
	
	public Integer getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public String getRomaji() {
		return romaji;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setRomaji(String romaji) {
		this.romaji = romaji;
	}
}

SyainRepository.java

package com.example.demo;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.springframework.stereotype.Repository;

@Repository
public class SyainRepository {
	
	@SuppressWarnings("unchecked")
	public List<Syain> findAll(){
		List<Syain> syainList = null;
		
		SessionFactory sf = new Configuration().configure("hibernate-config.xml").addAnnotatedClass(Syain.class)
				.buildSessionFactory();
		
		Session session = sf.getCurrentSession();
		
		try {
			session.beginTransaction();
			syainList = session.createQuery("from Syain").list();
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			sf.close();
		}
		return syainList;
	}
}

MainController.java

package com.example.demo;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainController {
	@Autowired
	private SyainRepository syainRepository;
	
	@GetMapping("/test1")
	public List<Syain> get(){
		return syainRepository.findAll();
	}
}

http://localhost:8080/test1
[{“id”:1,”name”:”鈴木”,”romaji”:”suzuki”},{“id”:2,”name”:”田中”,”romaji”:”tanaka”},{“id”:3,”name”:”佐藤”,”romaji”:”sato”},{“id”:4,”name”:”武田”,”romaji”:”takeda”}]

jdbc使えるなら、Hibernateを使う理由がイマイチわからんが、とにかくOK

[Spring Boot2.4.2] SpringJDBCでinsert

serviceは、selectと変更なし

SyainRepository.java

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class SyainRepository {
	private final JdbcTemplate jdbcTemplate;
	
	@Autowired
	public SyainRepository(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public void insertSyain(Syain syain) {
		jdbcTemplate.update("INSERT INTO syain(id,name,romaji) Values(?,?,?)",
				syain.getId(),syain.getName(),syain.getRomaji());
	}
}

MainController.java

package com.example.demo;
import java.time.LocalDateTime;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test1")
public class MainController {
	@Autowired
	private SyainRepository syainRepository;
	
	@GetMapping
	public String index(Model model) {
		Syain syain = new Syain();
		syain.setId(4);
		syain.setName("武田");
		syain.setRomaji("takeda");
		syainRepository.insertSyain(syain);
		return "test1/index";
	}
}

$ psql -U root test
psql (13.1)
Type “help” for help.

test=> select * from syain;
id | name | romaji
—-+——+——–
1 | 鈴木 | suzuki
2 | 田中 | tanaka
3 | 佐藤 | sato
(3 rows)

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Check</title>
  </head>
  <body>
    ok
  </body>
</html>

http://localhost:8080/test1

test=> select * from syain;
id | name | romaji
—-+——+——–
1 | 鈴木 | suzuki
2 | 田中 | tanaka
3 | 佐藤 | sato
4 | 武田 | takeda
(4 rows)

なるほど、CRUDはJDBCを使うのね、完全に理解した!

[Spring Boot2.4.2] SpringJDBCでselect

pom.xml

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>

Syain.java

package com.example.demo;

public class Syain {
	
	private Integer id;
	private String name;
	private String romaji;
	
	public Integer getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public String getRomaji() {
		return romaji;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setRomaji(String romaji) {
		this.romaji = romaji;
	}
}

SyainRepository.java
L mapとは、「キー」と「値」をペアにして複数のデータを格納できるもの
-> 連想配列みたいなものか。。

package com.example.demo;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class SyainRepository {
	private final JdbcTemplate jdbcTemplate;
	
	@Autowired
	public SyainRepository(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public List<Syain> getAll(){
		String sql = "select id, name, romaji from syain";
		List<Map<String, Object>>syainList = jdbcTemplate.queryForList(sql);
		List<Syain> list = new ArrayList<>();
		for(Map<String,Object> str1: syainList) {
			Syain syain = new Syain();
			syain.setId((int)str1.get("id"));
			syain.setName((String)str1.get("name"));
			syain.setRomaji((String)str1.get("romaji"));
			list.add(syain);
		}
		return list;
	}
}

MainController.java

package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test1")
public class MainController {
	@Autowired
	private SyainRepository syainRepository;
	
	@GetMapping
	public String index(Model model) {
		List<Syain> list = syainRepository.getAll();
		model.addAttribute("SyainList", list);
		return "test1/index";
	}
}

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Check</title>
  </head>
  <body>
    <table>
    	<tr>
    		<th>id</th><th>name</th><th>romaji</th>
    	</tr>
    	<tr th:each="list : ${SyainList}">
    		<td th:text="${list.id}"></td>
    		<td th:text="${list.name}"></td>
    		<td th:text="${list.romaji}"></td>
    	</tr>
    </table>
  </body>
</html>

なんかもう殆どSpringBootでアプリ作れるような気がしてきた。

[Spring Boot2.4.2] Postgresからselect

### Postgresにデータ挿入
psql -U root test
CREATE TABLE syain (
id SERIAL NOT NULL,
name varchar(255),
romaji varchar(255),
PRIMARY KEY(id)
);

INSERT INTO syain (name, romaji) VALUES (‘鈴木’,’suzuki’);
INSERT INTO syain (name, romaji) VALUES (‘田中’,’tanaka’);
INSERT INTO syain (name, romaji) VALUES (‘佐藤’,’sato’);
test=> select * from syain;
id | name | romaji
—-+——+——–
1 | 鈴木 | suzuki
2 | 田中 | tanaka
3 | 佐藤 | sato
(3 rows)

pom.xml

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>

application.properties

spring.jpa.database=POSTGRESQL
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.username=root
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.format_sql=true
spring.datasource.sql-script-encoding=UTF-8

Syain.java

package com.example.demo;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;

@Entity
@Table(name="syain")
public class Syain {
	@Id
	private Integer id;
	private String name;
	private String romaji;
	
	public Integer getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public String getRomaji() {
		return romaji;
	}
}

SyainRepository.java

package com.example.demo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface SyainRepository extends JpaRepository<Syain, Integer>{
}

MainController.java

package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainController {
	@Autowired
	private SyainRepository syainRepository;
	
	@GetMapping("/test1")
	public List<Syain> get() {
		return syainRepository.findAll();
	}
}

うおおおおおおおおおおおおおおおおお
きたあああああああああああああああああああああああ

[Spring Boot2.4.2] Thymeleafで共通レイアウトを使用する

src/main/resources/templates/test1/partial1.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<header th:fragment="header1">
<p style="background:yellow;">ヘッダーです</p>
</header>
<footer th:fragment="footer1">
<p style="background:yellow;">フッターです</p>
</footer>
</html>

src/main/resources/templates/test1/index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>Check</title>
  </head>
  <body>
    <div th:replace="text1/partial1::header1"></div>
    <p>テスト</p>
    <div th:replace="text1/partial1::footer1"></div>
  </body>
</html>

MainController.java

package com.example.demo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test1")
public class MainController {
	
	@GetMapping
	public String index() {
		return "test1/index";
	}
}

ほう、中々面白い

地道にやってくのが手堅いか。。

### Bootstrapを追加
pom.xml

		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>bootstrap</artifactId>
			<version>4.5.2</version>
		</dependency>

index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/4.5.2/css/bootstrap.min.css}">
    <title>Check</title>
  </head>
  <body>
    <span class="badge badge-primary">Primary</span>
<span class="badge badge-secondary">Secondary</span>
<span class="badge badge-success">Success</span>
<span class="badge badge-danger">Danger</span>
<span class="badge badge-warning">Warning</span>
<span class="badge badge-info">Info</span>
<span class="badge badge-light">Light</span>
<span class="badge badge-dark">Dark</span>
  </body>
</html>

pom.xmlの反映は、コンパイルし直さないといけない。