# This workflow will build a golang project # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go name: Go on: push: branches: [ "*" ] pull_request: env: TARGET: 'iqn.2016-09.com.gotgt.gostor:example_tgt_0' TGT_CFG: '{"storages":[{"deviceID":1000,"path":"file:/var/tmp/disk.img","online":true}],"iscsiportals":[{"id":0,"portal":"127.0.0.1:3260"}],"iscsitargets":{"iqn.2016-09.com.gotgt.gostor:example_tgt_0":{"tpgts":{"1":[0]},"luns":{"0":1000}}}}' jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.24' check-latest: true - name: Depend install run: | sudo apt-get update sudo apt-get install libcunit1 libcunit1-doc libcunit1-dev open-iscsi make libnuma-dev -y - name: Gofmt verify run: hack/verify-gofmt.sh - name: Build run: make - name: Unit Test run: go test -v ./pkg/... ./mock/... - name: S3 Backend Store Test run: go test -tags s3integration -v ./pkg/scsi/backingstore/s3store/ - name: Function test run: | dd if=/dev/zero of=/var/tmp/disk.img bs=1024 count=102400 mkdir $HOME/.gotgt echo '${{env.TGT_CFG}}' > $HOME/.gotgt/config.json ./_output/cmd/bin/gotgt daemon --log debug 1>/dev/null 2>&1 & git clone https://github.com/gostor/libiscsi $HOME/libiscsi cd $HOME/libiscsi sudo ci/install.sh export ISCSITEST=yes ./autogen.sh ./configure 2>&1 >/dev/null make 2>&1 >/dev/null echo "=== Starting Comprehensive libiscsi Tests (60+ tests) ===" # Inquiry Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.Standard iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.AllocLength iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.MandatoryVPDSBC iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.SupportedVPD iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.VersionDescriptors iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Inquiry.EVPD iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Mandatory Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Mandatory iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.ModeSense6 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.NoMedia iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Read Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Read6 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Read10 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Read12 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Read16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.ReadOnly iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Read Capacity Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.ReadCapacity10 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.ReadCapacity16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Write Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Write10 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Write12 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Write16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.WriteVerify10 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.WriteVerify12 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.WriteVerify16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Write Same Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.WriteSame10.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.WriteSame16.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Verify Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Verify10 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Verify12 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Verify16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Prefetch Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Prefetch10 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Prefetch16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Synchronize Cache Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.SynchronizeCache10 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 || true ./test-tool/iscsi-test-cu -d -A --test=ALL.SynchronizeCache16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 || true # Reserve/Release Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Reserve6.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Persistent Reservation Tests (known issues with write-path sense data) ./test-tool/iscsi-test-cu -d -A --test=ALL.PrinReadKeys.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 || true ./test-tool/iscsi-test-cu -d -A --test=ALL.PrinReportCapabilities.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 || true # Unmap Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.Unmap.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Unmap.VPD iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.Unmap.ZeroBlocks iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Read Defect Data Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.ReadDefectData10.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.ReadDefectData12.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # Other SCSI Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.PreventAllow iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.StartStopUnit iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.TestUnitReady iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./test-tool/iscsi-test-cu -d -A --test=ALL.ReportSupportedOpcodes.Simple iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # iSCSI Protocol Tests ./test-tool/iscsi-test-cu -d -A --test=ALL.iSCSITMF iscsi://127.0.0.1:3260/${{env.TARGET}}/0 || true ./test-tool/iscsi-test-cu -d -A --test=ALL.iSCSIcmdsn iscsi://127.0.0.1:3260/${{env.TARGET}}/0 echo "=== libiscsi Tests Completed ===" # Utility tests ./utils/iscsi-ls -s iscsi://127.0.0.1:3260/${{env.TARGET}} ./utils/iscsi-inq iscsi://127.0.0.1:3260/${{env.TARGET}}/0 ./utils/iscsi-readcapacity16 iscsi://127.0.0.1:3260/${{env.TARGET}}/0 # iscsi initiator test sudo iscsiadm -m discovery -t sendtargets -p 127.0.0.1 sudo iscsiadm -m node -L all sudo iscsiadm -m session sudo fdisk -l echo -e "n\np\n1\n\n\nt\nc\na\nw" | sudo fdisk /dev/sdb sudo mkfs.ext3 /dev/sdb1 sudo mkdir -p /var/tmp/test sudo mount /dev/sdb1 /var/tmp/test sudo ls -lh /var/tmp/test/ - name: CLI management test run: | API="http://127.0.0.1:23457" echo "=== CLI Management API Tests ===" # 1. List targets - should show the target from config echo "--- list target ---" curl -sf "$API/target/list" | tee /tmp/list_target.out grep -q "${{env.TARGET}}" /tmp/list_target.out echo "PASS: list target shows configured target" # 2. List LUs for the existing target echo "--- list lu ---" curl -sf "$API/lu/list?target=${{env.TARGET}}" | tee /tmp/list_lu.out echo "" # Verify it returns a JSON array (may be empty or have LU 0) python3 -c "import json,sys; data=json.load(sys.stdin); assert isinstance(data,list)" < /tmp/list_lu.out echo "PASS: list lu returns valid JSON array" # 3. List TPGTs for the existing target echo "--- list tpgt ---" curl -sf "$API/target/tpgt/list?target=${{env.TARGET}}" | tee /tmp/list_tpgt.out echo "" python3 -c "import json,sys; data=json.load(sys.stdin); assert isinstance(data,list)" < /tmp/list_tpgt.out echo "PASS: list tpgt returns valid JSON array" # 4. Create a new target via API echo "--- create target ---" NEW_TARGET="iqn.2016-09.com.gotgt.gostor:ci_test_tgt" curl -sf -X POST "$API/target/create" \ -H "Content-Type: application/json" \ -d "{\"Name\":\"$NEW_TARGET\"}" | tee /tmp/create_target.out echo "" grep -q "$NEW_TARGET" /tmp/create_target.out echo "PASS: create target succeeded" # 5. Verify new target appears in list echo "--- verify new target in list ---" curl -sf "$API/target/list" | tee /tmp/list_target2.out echo "" grep -q "$NEW_TARGET" /tmp/list_target2.out echo "PASS: new target visible in list" # 6. Create a new LU on the new target echo "--- create lu ---" dd if=/dev/zero of=/var/tmp/ci_disk.img bs=1024 count=10240 2>/dev/null curl -sf -X POST "$API/lu/create" \ -H "Content-Type: application/json" \ -d "{\"targetName\":\"$NEW_TARGET\",\"deviceID\":2000,\"lun\":0,\"path\":\"file:/var/tmp/ci_disk.img\",\"blockShift\":9}" \ -o /dev/null -w "%{http_code}" | tee /tmp/create_lu_status.out echo "" grep -q "201" /tmp/create_lu_status.out echo "PASS: create lu returned 201" # 7. Verify new LU appears in list echo "--- verify new lu in list ---" curl -sf "$API/lu/list?target=$NEW_TARGET" | tee /tmp/list_lu2.out echo "" python3 -c "import json,sys; data=json.load(sys.stdin); assert len(data)==1, f'expected 1 LU, got {len(data)}'" < /tmp/list_lu2.out echo "PASS: new LU visible in list" # 8. Remove the LU echo "--- remove lu ---" curl -sf -X DELETE "$API/lu/delete" \ -H "Content-Type: application/json" \ -d "{\"targetName\":\"$NEW_TARGET\",\"lun\":0}" \ -o /dev/null -w "%{http_code}" | tee /tmp/rm_lu_status.out echo "" grep -q "204" /tmp/rm_lu_status.out echo "PASS: remove lu returned 204" # 9. Verify LU is gone echo "--- verify lu removed ---" curl -sf "$API/lu/list?target=$NEW_TARGET" | tee /tmp/list_lu3.out echo "" python3 -c "import json,sys; data=json.load(sys.stdin); assert data is None or len(data)==0, f'expected 0 LUs, got {data}'" < /tmp/list_lu3.out echo "PASS: LU no longer in list" # 10. Remove the target echo "--- remove target ---" curl -sf -X DELETE "$API/target/$NEW_TARGET?force=1" \ -o /dev/null -w "%{http_code}" | tee /tmp/rm_target_status.out echo "" grep -q "204" /tmp/rm_target_status.out echo "PASS: remove target returned 204" # 11. Verify target is gone echo "--- verify target removed ---" curl -sf "$API/target/list" | tee /tmp/list_target3.out echo "" if grep -q "$NEW_TARGET" /tmp/list_target3.out; then echo "FAIL: target still present after removal" exit 1 fi echo "PASS: target no longer in list" echo "=== All CLI Management API Tests Passed ==="