spec/cloud/google_service_spec.rb in knife-google-2.1.0 vs spec/cloud/google_service_spec.rb in knife-google-2.2.0

- old
+ new

@@ -59,10 +59,11 @@ end before do service.ui = Chef::Knife::UI.new($stdout, $stderr, $stdin, {}) allow(service.ui).to receive(:msg) + allow(service.ui).to receive(:error) allow(service).to receive(:connection).and_return(connection) end describe '#connection' do it "returns a properly configured ComputeService" do @@ -187,19 +188,21 @@ describe '#validate_server_create_options!' do let(:options) do { machine_type: "test_type", network: "test_network", + subnet: "test_subnet", public_ip: "public_ip", image: "test_image", image_project: "test_image_project", } end before do allow(service).to receive(:valid_machine_type?).and_return(true) allow(service).to receive(:valid_network?).and_return(true) + allow(service).to receive(:valid_subnet?).and_return(true) allow(service).to receive(:valid_public_ip_setting?).and_return(true) allow(service).to receive(:image_search_for).and_return(true) end it "does not raise an exception when all parameters are supplied and accurate" do @@ -214,10 +217,15 @@ it "raises an exception if the network is not valid" do expect(service).to receive(:valid_network?).with("test_network").and_return(false) expect { service.validate_server_create_options!(options) }.to raise_error(RuntimeError) end + it "raises an exception if the network is not valid" do + expect(service).to receive(:valid_subnet?).with("test_subnet").and_return(false) + expect { service.validate_server_create_options!(options) }.to raise_error(RuntimeError) + end + it "raises an exception if the public ip setting is not valid" do expect(service).to receive(:valid_public_ip_setting?).with("public_ip").and_return(false) expect { service.validate_server_create_options!(options) }.to raise_error(RuntimeError) end @@ -265,10 +273,24 @@ service.valid_network?("test_network") end end + describe '#valid_subnet?' do + it "returns false if no subnet was specified" do + expect(service.valid_subnet?(nil)).to eq(false) + end + + it "checks the network using check_api_call" do + expect(service).to receive(:region).and_return("test_region") + expect(connection).to receive(:get_subnetwork).with(project, "test_region", "test_subnet") + expect(service).to receive(:check_api_call).and_call_original + + service.valid_subnet?("test_subnet") + end + end + describe '#image_exist?' do it "checks the image using check_api_call" do expect(connection).to receive(:get_image).with("image_project", "image_name") expect(service).to receive(:check_api_call).and_call_original @@ -310,10 +332,18 @@ expect(IPAddr).to receive(:new).with("1.2.3.4") expect(service.valid_ip_address?("1.2.3.4")).to eq(true) end end + describe '#region' do + it "returns the region for a given zone" do + zone_obj = double("zone_obj", region: "/path/to/test_region") + expect(connection).to receive(:get_zone).with(project, zone).and_return(zone_obj) + expect(service.region).to eq("test_region") + end + end + describe '#instance_object_for' do let(:instance_object) { double("instance_object") } let(:options) do { name: "test_instance", @@ -451,36 +481,49 @@ expect(service.image_search_for("test_image", "test_project")).to eq("image_url") end end context "when the user does not supply an image project" do - context "when the image exists in the user's project" do - it "returns the image URL" do - expect(service).to receive(:image_url_for).with(project, "test_image").and_return("image_url") - expect(service.image_search_for("test_image", nil)).to eq("image_url") + context "when the image provided is an alias" do + it "returns the alias URL" do + expect(service).to receive(:image_alias_url).with("test_image").and_return("image_alias_url") + expect(service.image_search_for("test_image", nil)).to eq("image_alias_url") end end - context "when the image does not exist in the user's project" do + context "when the image provided is not an alias" do before do - expect(service).to receive(:image_url_for).with(project, "test_image").and_return(nil) + expect(service).to receive(:image_alias_url).and_return(nil) end - context "when the image matches a known public project" do - it "returns the image URL from the public project" do - expect(service).to receive(:public_project_for_image).with("test_image").and_return("public_project") - expect(service).to receive(:image_url_for).with("public_project", "test_image").and_return("image_url") + context "when the image exists in the user's project" do + it "returns the image URL" do + expect(service).to receive(:image_url_for).with(project, "test_image").and_return("image_url") expect(service.image_search_for("test_image", nil)).to eq("image_url") end end - context "when the image does not match a known project" do - it "returns nil" do - expect(service).to receive(:public_project_for_image).with("test_image").and_return(nil) - expect(service).not_to receive(:image_url_for) - expect(service.image_search_for("test_image", nil)).to eq(nil) + context "when the image does not exist in the user's project" do + before do + expect(service).to receive(:image_url_for).with(project, "test_image").and_return(nil) end + + context "when the image matches a known public project" do + it "returns the image URL from the public project" do + expect(service).to receive(:public_project_for_image).with("test_image").and_return("public_project") + expect(service).to receive(:image_url_for).with("public_project", "test_image").and_return("image_url") + expect(service.image_search_for("test_image", nil)).to eq("image_url") + end + end + + context "when the image does not match a known project" do + it "returns nil" do + expect(service).to receive(:public_project_for_image).with("test_image").and_return(nil) + expect(service).not_to receive(:image_url_for) + expect(service.image_search_for("test_image", nil)).to eq(nil) + end + end end end end end @@ -494,10 +537,54 @@ expect(service).to receive(:image_exist?).with("image_project", "image_name").and_return(true) expect(service.image_url_for("image_project", "image_name")).to eq("projects/image_project/global/images/image_name") end end + describe '#image_alias_url' do + context "when the image_alias is not a valid alias" do + it "returns nil" do + expect(service.image_alias_url("fake_alias")).to eq(nil) + end + end + + context "when the image_alias is a valid alias" do + before do + allow(connection).to receive(:list_images).and_return(response) + end + + context "when the response contains no images" do + let(:response) { double("response", items: []) } + + it "returns nil" do + expect(service.image_alias_url("centos-7")).to eq(nil) + end + end + + context "when the response contains images but none match the name" do + let(:image1) { double("image1", name: "centos-6") } + let(:image2) { double("image2", name: "centos-6") } + let(:image3) { double("image3", name: "ubuntu-14") } + let(:response) { double("response", items: [ image1, image2, image3 ]) } + + it "returns nil" do + expect(service.image_alias_url("centos-7")).to eq(nil) + end + end + + context "when the response contains images that match the name" do + let(:image1) { double("image1", name: "centos-7-v20160201", self_link: "image1_selflink") } + let(:image2) { double("image2", name: "centos-7-v20160301", self_link: "image2_selflink") } + let(:image3) { double("image3", name: "centos-6", self_link: "image3_selflink") } + let(:response) { double("response", items: [ image1, image2, image3 ]) } + + it "returns the link for image2 which is the most recent image" do + expect(service.image_alias_url("centos-7")).to eq("image2_selflink") + end + end + end + end + describe '#boot_disk_name_for' do it "returns the boot disk name if supplied by the user" do options = { name: "instance_name", boot_disk_name: "disk_name" } expect(service.boot_disk_name_for(options)).to eq("disk_name") end @@ -541,39 +628,79 @@ expect(service.instance_metadata_for(metadata)).to eq(metadata_obj) end end describe '#instance_network_interfaces_for' do - it "returns an array containing a properly-formatted interface" do - interface = double("interface") - options = { network: "test_network", public_ip: "public_ip" } + let(:interface) { double("interface" ) } + let(:options) { { network: "test_network", public_ip: "public_ip" } } - expect(service).to receive(:network_url_for).with("test_network").and_return("network_url") - expect(service).to receive(:instance_access_configs_for).with("public_ip").and_return("access_configs") + before do + allow(service).to receive(:network_url_for) + allow(service).to receive(:subnet_url_for) + allow(service).to receive(:instance_access_configs_for) + allow(Google::Apis::ComputeV1::NetworkInterface).to receive(:new).and_return(interface) + allow(interface).to receive(:network=) + allow(interface).to receive(:subnetwork=) + allow(interface).to receive(:access_configs=) + end + it "creates a network interface object and returns it" do expect(Google::Apis::ComputeV1::NetworkInterface).to receive(:new).and_return(interface) + expect(service.instance_network_interfaces_for(options)).to eq([interface]) + end + + it "sets the network" do + expect(service).to receive(:network_url_for).with("test_network").and_return("network_url") expect(interface).to receive(:network=).with("network_url") + service.instance_network_interfaces_for(options) + end + + it "sets the access configs" do + expect(service).to receive(:instance_access_configs_for).with("public_ip").and_return("access_configs") expect(interface).to receive(:access_configs=).with("access_configs") + service.instance_network_interfaces_for(options) + end - expect(service.instance_network_interfaces_for(options)).to eq([interface]) + it "does not set a subnetwork" do + expect(service).not_to receive(:subnet_url_for) + expect(interface).not_to receive(:subnetwork=) + service.instance_network_interfaces_for(options) end + + context "when a subnet exists" do + let(:options) { { network: "test_network", subnet: "test_subnet", public_ip: "public_ip" } } + + it "sets the subnetwork" do + expect(service).to receive(:subnet_url_for).with("test_subnet").and_return("subnet_url") + expect(interface).to receive(:subnetwork=).with("subnet_url") + service.instance_network_interfaces_for(options) + end + end end describe '#network_url_for' do it "returns a properly-formatted network URL" do expect(service.network_url_for("test_network")).to eq("projects/test_project/global/networks/test_network") end end + describe '#subnet_url_for' do + it "returns a properly-formatted subnet URL" do + expect(service).to receive(:region).and_return("test_region") + expect(service.subnet_url_for("test_subnet")).to eq("projects/test_project/regions/test_region/subnetworks/test_subnet") + end + end + describe '#instance_scheduling_for' do it "returns a properly-formatted scheduling object" do scheduling = double("scheduling") - options = { auto_restart: "auto_restart", auto_migrate: "auto_migrate" } + options = { auto_restart: "auto_restart", auto_migrate: "auto_migrate", preemptible: "preempt" } expect(service).to receive(:migrate_setting_for).with("auto_migrate").and_return("host_maintenance") expect(Google::Apis::ComputeV1::Scheduling).to receive(:new).and_return(scheduling) expect(scheduling).to receive(:automatic_restart=).with("auto_restart") expect(scheduling).to receive(:on_host_maintenance=).with("host_maintenance") + expect(scheduling).to receive(:preemptible=).with("preempt") expect(service.instance_scheduling_for(options)).to eq(scheduling) end end